

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=&#34;auto&#34;>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/favicon.ico">
  <link rel="icon" href="/img/favicon.ico">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="description" content="叶尘的技术升级小木屋">
  <meta name="author" content="叶尘">
  <meta name="keywords" content="">
  
  <title>Vue脚手架 - 叶尘的技术升级小木屋</title>

  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@4.0.0/github-markdown.min.css" />
  <link  rel="stylesheet" href="/lib/hint/hint.min.css" />

  
    
    
      
      <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@10.7.2/styles/github-gist.min.css" />
    
  

  
    <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css" />
  



<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_ba1fz6golrf.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_kmeydafke9r.css">


<link  rel="stylesheet" href="/css/main.css" />

<!-- 自定义样式保持在最底部 -->

  
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/bynotes/texiao/source/css/shubiao.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/bynotes/texiao/source/css/gundongtiao.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/bynotes/texiao/source/css/daziyanse.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/bynotes/texiao/source/css/toubudaziji.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css">



  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    var CONFIG = {"hostname":"www.yechen-blog.cn","root":"/","version":"1.8.11","typing":{"enable":true,"typeSpeed":70,"cursorChar":"_","loop":false},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"right","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"copy_btn":true,"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":false,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null}},"search_path":"/local-search.xml"};
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
<meta name="generator" content="Hexo 5.4.0"></head>


<body>
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand"
       href="/">&nbsp;<strong>YECHEN</strong>&nbsp;</a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-qrcode"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/playlist/">
                <i class="iconfont icon-music"></i>
                音乐
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item dropdown">
              <a class="nav-link dropdown-toggle" target="_self" role="button"
                 data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                <i class="iconfont icon-books"></i>
                链接
              </a>
              <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://hexo.fluid-dev.com/">
                    
                    主题博客
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://hexo.fluid-dev.com/docs/guide/">
                    
                    配置指南
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://hexo.fluid-dev.com/docs/icon/">
                    
                    图标用法
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://www.bilibili.com">
                    
                    哔哩哔哩
                  </a>
                
              </div>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" data-toggle="modal" data-target="#modalSearch">&nbsp;<i
                class="iconfont icon-search"></i>&nbsp;</a>
          </li>
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner" id="banner" parallax=true
         style="background: url('/img/banner.jpg') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="page-header text-center fade-in-up">
            <span class="h2" id="subtitle" title="Vue脚手架">
              
            </span>

            
              <div class="mt-3">
  
    <span class="post-meta mr-2">
      <i class="iconfont icon-author" aria-hidden="true"></i>
      叶尘
    </span>
  
  
    <span class="post-meta">
      <i class="iconfont icon-date-fill" aria-hidden="true"></i>
      <time datetime="2021-10-02 14:30" pubdate>
        星期六, 十月 2日 2021, 2:30 下午
      </time>
    </span>
  
</div>

<div class="mt-1">
  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      16.3k 字
    </span>
  

  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      244
       分钟
    </span>
  

  
  
    
      <!-- LeanCloud 统计文章PV -->
      <span id="leancloud-page-views-container" class="post-meta" style="display: none">
        <i class="iconfont icon-eye" aria-hidden="true"></i>
        <span id="leancloud-page-views"></span> 次
      </span>
    
  
</div>

            
          </div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div class="py-5" id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">Vue脚手架</h1>
            
            <div class="markdown-body">
              <h1 id="vue-cli"><a href="#vue-cli" class="headerlink" title="vue-cli"></a>vue-cli</h1><h2 id="1-分析脚手架"><a href="#1-分析脚手架" class="headerlink" title="1.分析脚手架"></a>1.分析脚手架</h2><h3 id="1-1-脚手架文件结构"><a href="#1-1-脚手架文件结构" class="headerlink" title="1.1 脚手架文件结构"></a>1.1 脚手架文件结构</h3><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs stylus">├── node_modules <br>├── public<br>│   ├── favicon<span class="hljs-selector-class">.ico</span>: 页签图标<br>│   └── index<span class="hljs-selector-class">.html</span>: 主页面<br>├── <span class="hljs-attribute">src</span><br>│   ├── assets: 存放静态资源<br>│   │   └── logo<span class="hljs-selector-class">.png</span><br>│   │── component: 存放组件<br>│   │   └── HelloWorld<span class="hljs-selector-class">.vue</span><br>│   │── App<span class="hljs-selector-class">.vue</span>: 汇总所有组件<br>│   │── <span class="hljs-selector-tag">main</span><span class="hljs-selector-class">.js</span>: 入口文件<br>├── <span class="hljs-selector-class">.gitignore</span>: git版本管制忽略的配置<br>├── babel<span class="hljs-selector-class">.config</span><span class="hljs-selector-class">.js</span>: babel的配置文件<br>├── package<span class="hljs-selector-class">.json</span>: 应用包配置文件 <br>├── README<span class="hljs-selector-class">.md</span>: 应用描述文件<br>├── package-lock.json：包版本控制文件<br></code></pre></td></tr></table></figure>

<h3 id="1-2-自己使用"><a href="#1-2-自己使用" class="headerlink" title="1.2 自己使用"></a>1.2 自己使用</h3><p>将之前未能运行的单文件组件项目放到脚手架环境下运行</p>
<p>在 components 目录下存放 School.vue 和 Student.vue</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;!-- 组件的结构 --&gt;<br>  &lt;div class=&quot;demo&quot;&gt;<br>    &lt;h2&gt;学校名称：&#123;&#123;name&#125;&#125;&lt;/h2&gt;<br>    &lt;h2&gt;学校地址：&#123;&#123;address&#125;&#125;&lt;/h2&gt;<br>    &lt;button @click=&quot;showSchoolName&quot;&gt;点我提示学校名&lt;/button&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>  // 组件的交互相关的代码<br>  export default &#123;<br>    name: &quot;School&quot;,<br>    data() &#123;<br>      return &#123;<br>        name: &quot;尚硅谷&quot;,<br>        address: &quot;北京&quot;<br>      &#125;<br>    &#125;,<br>    methods: &#123;<br>      showSchoolName() &#123;<br>        alert(this.name);<br>      &#125;<br>    &#125;<br>  &#125;<br>&lt;/script&gt;<br><br>&lt;style&gt;<br>  /*组件的样式*/<br>  .demo &#123;<br>    background: orange;<br>  &#125;<br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;div&gt;<br>    &lt;h2&gt;学生姓名：&#123;&#123;name&#125;&#125;&lt;/h2&gt;<br>    &lt;h2&gt;学生年龄：&#123;&#123;age&#125;&#125;&lt;/h2&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>  export default &#123;<br>    name: &quot;Student&quot;,<br>    data() &#123;<br>      return &#123;<br>        name: &quot;张三&quot;,<br>        age: 20<br>      &#125;<br>    &#125;<br>  &#125;<br>&lt;/script&gt;<br></code></pre></td></tr></table></figure>

<p>在 src 目录下替换 App.vue</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;div&gt;<br>    &lt;School&gt;&lt;/School&gt;<br>    &lt;Student&gt;&lt;/Student&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>  // 导入组件<br>  import School from &quot;./components/School&quot;;<br>  import Student from &quot;./components/Student&quot;;<br><br>  export default &#123;<br>    name: &quot;App&quot;,<br>    components: &#123;<br>      School,<br>      Student<br>    &#125;<br>  &#125;<br>&lt;/script&gt;<br></code></pre></td></tr></table></figure>

<p>main.js 和 index.html 直接使用脚手架生成的就好了</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * 该文件是整个项目的入口</span><br><span class="hljs-comment"> */</span><br><span class="hljs-comment">// 引入 Vue 依赖</span><br><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;vue&#x27;</span><br><span class="hljs-comment">// 引入 App 组件</span><br><span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;./App.vue&#x27;</span><br><span class="hljs-comment">// 关闭 Vue 的生产提示</span><br>Vue.config.productionTip = <span class="hljs-literal">false</span><br><span class="hljs-comment">// 创建 Vue 实例（vm）</span><br><span class="hljs-keyword">new</span> Vue(&#123;<br>  <span class="hljs-comment">// 将 App 组件放入容器中（这里和之前学过的写法不一样，之后再说）</span><br>  <span class="hljs-attr">render</span>: <span class="hljs-function"><span class="hljs-params">h</span> =&gt;</span> h(App),<br>&#125;).$mount(<span class="hljs-string">&#x27;#app&#x27;</span>)<span class="hljs-comment">// 绑定 id 为 app 的容器</span><br></code></pre></td></tr></table></figure>

<p>注意 index.html 位于 public 目录下</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">&quot;&quot;</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">&quot;utf-8&quot;</span>&gt;</span><br>    <span class="hljs-comment">&lt;!-- 针对IE浏览器的一个特殊配置，含义是让IE浏览器以最高的渲染级别渲染页面 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">http-equiv</span>=<span class="hljs-string">&quot;X-UA-Compatible&quot;</span> <span class="hljs-attr">content</span>=<span class="hljs-string">&quot;IE=edge&quot;</span>&gt;</span><br>    <span class="hljs-comment">&lt;!-- 开启移动端的理想视口 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;viewport&quot;</span> <span class="hljs-attr">content</span>=<span class="hljs-string">&quot;width=device-width,initial-scale=1.0&quot;</span>&gt;</span><br>    <span class="hljs-comment">&lt;!-- 配置页签图标，这里的 BASE_URL 指定的路径就是 public 目录 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">&quot;icon&quot;</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&quot;&lt;%= BASE_URL %&gt;favicon.ico&quot;</span>&gt;</span><br>    <span class="hljs-comment">&lt;!-- 配置网页标题 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>硅谷系统<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span><br><span class="hljs-comment">&lt;!-- 当浏览器不支持js时noscript中的元素就会被渲染 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">noscript</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>We&#x27;re sorry but &lt;%= htmlWebpackPlugin.options.title %&gt; doesn&#x27;t work properly without JavaScript enabled. Please enable it to continue.<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">noscript</span>&gt;</span><br><span class="hljs-comment">&lt;!-- 容器 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;app&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br><span class="hljs-comment">&lt;!-- built files will be auto injected --&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>在根目录下执行 <code>npm run serve</code> 命令</p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210804/image.9bvk9l3fp14.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<h3 id="1-3-关于-main-js-中使用-render-函数的说明"><a href="#1-3-关于-main-js-中使用-render-函数的说明" class="headerlink" title="1.3 关于 main.js 中使用 render 函数的说明"></a>1.3 关于 main.js 中使用 render 函数的说明</h3><p>以我们之前学习的写法应该这样创建 vm 实例对象</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">new</span> Vue(&#123;<br>    <span class="hljs-attr">el</span>: <span class="hljs-string">&#x27;#app&#x27;</span>,<br>    <span class="hljs-attr">templata</span>: <span class="hljs-string">`&lt;App&gt;&lt;/App&gt;`</span>,<br>    <span class="hljs-attr">components</span>: &#123;App&#125;<br>&#125;)<br></code></pre></td></tr></table></figure>

<p>那么就这样替换一下 main.js</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * 该文件是整个项目的入口</span><br><span class="hljs-comment"> */</span><br><span class="hljs-comment">// 引入 Vue 依赖</span><br><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;vue&#x27;</span><br><span class="hljs-comment">// 引入 App 组件</span><br><span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;./App.vue&#x27;</span><br><span class="hljs-comment">// 关闭 Vue 的生产提示</span><br>Vue.config.productionTip = <span class="hljs-literal">false</span><br><span class="hljs-comment">// 创建 Vue 实例（vm）</span><br><span class="hljs-keyword">new</span> Vue(&#123;<br>  <span class="hljs-attr">el</span>: <span class="hljs-string">&#x27;#app&#x27;</span>,<br>  <span class="hljs-attr">templata</span>: <span class="hljs-string">`&lt;App&gt;&lt;/App&gt;`</span>,<br>  <span class="hljs-attr">components</span>: &#123;App&#125;<br>&#125;)<br></code></pre></td></tr></table></figure>

<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210804/image.6vf9lqt62q00.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<p>Vue 脚手架为我们生成的就是 main.js 就是使用的第一种解决办法。</p>
<p>现在我们来使用第二种办法解决。</p>
<p>在 <code>node_modules\vue\dist</code> 目录下存在很多不同版本的 Vue</p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210804/image.73k3jy7665w0.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<p>因此我们将 main.js 的 Vue 依赖改为 </p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-comment">// 引入 Vue 依赖</span><br><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;vue/dist/vue&#x27;</span><br></code></pre></td></tr></table></figure>

<p>运行成功</p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210804/image.pzit7cx447k.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<p><strong>关于不同版本的Vue</strong></p>
<ol>
<li>vue.js 与vue.runtime.xxx.js 的区别：<ol>
<li>vue.js 是完整版的 Vue，包含：核心功能 + 模板解析器。</li>
<li>vue.runtime.xxx.js 是运行版的 Vue，只包含：核心功能；没有模板解析器。</li>
</ol>
</li>
<li>因为 vue.runtime.xxx.js 没有模板解析器，所以不能使用 template 这个配置项，需要使用 render 函数接收到的 createElement 函数去指定具体内容。</li>
</ol>
<p>因此 render 函数是为了解决依赖中没有模板解析器。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-comment">// render 函数的详细写法</span><br><br><span class="hljs-comment">// createElement 是一个传入的的函数，调用该函数可以将组件放入容器中  </span><br><span class="hljs-function"><span class="hljs-title">render</span>(<span class="hljs-params">createElement</span>)</span> &#123;<br>    <span class="hljs-comment">// 当要将 html 中的标签放入容器中时，标签需要使用 &#x27;&#x27; 包起来，第二个参数可以写值</span><br>    <span class="hljs-comment">// return createElement(&#x27;h2&#x27;, &#x27;HelloWorld&#x27;);  </span><br>    <span class="hljs-keyword">return</span> createElement(App);<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-comment">// 根据 ES6 语法，render 函数就可以简写为</span><br><span class="hljs-comment">// h 即代表了 createElement 函数</span><br><span class="hljs-attr">render</span>: <span class="hljs-function"><span class="hljs-params">h</span> =&gt;</span> h(App)<br></code></pre></td></tr></table></figure>



<h3 id="1-4-修改默认配置项"><a href="#1-4-修改默认配置项" class="headerlink" title="1.4 修改默认配置项"></a>1.4 修改默认配置项</h3><p>在 Vue 脚手架中所有重要的文件名称和位置都是固定，我们不能更改，如果改变，会导致项目运行出现问题。</p>
<p>对于文件的默认配置，我们是接触不到的，但是可以使用命令 <code>vue inspect &gt; output.js</code> 生成一个 <code>output.js</code> 文件查看默认配置。</p>
<p>但此时我们还是改变不了配置，因此 Vue 脚手架为我们提供了一个配置文件 <code>vue.config.js</code> 可以对脚手架进行个性化定制。<a target="_blank" rel="noopener" href="https://cli.vuejs.org/zh/config/#%E5%85%A8%E5%B1%80-cli-%E9%85%8D%E7%BD%AE">参考官网</a></p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210804/image.4cydfajzv340.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<p>例如我们想将项目的入口文件改为 hello.js，我们就可以在 <code>vue.config.js</code> 中配置（注意这个文件要写在根目录下），同时也可以将语法检查关闭，方便之后学习调试。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-built_in">module</span>.exports = &#123;<br>    <span class="hljs-attr">pages</span>: &#123;<br>        <span class="hljs-attr">index</span>: &#123;<br>            <span class="hljs-comment">// page 的入口</span><br>            <span class="hljs-attr">entry</span>: <span class="hljs-string">&#x27;src/main.js&#x27;</span><br>        &#125;<br>    &#125;,<br>    <span class="hljs-comment">// 关闭语法检查</span><br>    <span class="hljs-attr">lintOnSave</span>: <span class="hljs-literal">false</span><br>&#125;<br></code></pre></td></tr></table></figure>



<h2 id="2-ref-属性"><a href="#2-ref-属性" class="headerlink" title="2.ref 属性"></a>2.ref 属性</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;div&gt;<br>    &lt;h1 v-text=&quot;msg&quot; ref=&quot;title&quot;&gt;&lt;/h1&gt;<br>    &lt;School ref=&#x27;school&#x27;&gt;&lt;/School&gt;<br>    &lt;button @click=&quot;showDOM&quot; ref=btn&gt;点我输出上方的 DOM 元素&lt;/button&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>import School from &quot;./components/School&quot;;<br><br>export default &#123;<br>  name: &quot;App&quot;,<br>  data()  &#123;<br>    return &#123;<br>      msg: &#x27;欢迎学习 Vue&#x27;<br>    &#125;<br>  &#125;,<br>  components: &#123;School&#125;,<br>  methods: &#123;<br>    showDOM() &#123;<br>      console.log(this.$refs.title);// 真实 DOM 元素<br>      console.log(this.$refs.school);// school 组件的实例对象（vc）<br>      console.log(this.$refs.btn);// 真实 DOM 元素<br>    &#125;<br>  &#125;<br>&#125;<br>&lt;/script&gt;<br><br>&lt;style scoped&gt;<br><br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>

<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210804/image.5v6107iab680.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<blockquote>
<p>总结 ref：</p>
<ol>
<li>被用来给元素或子组件<strong>注册引用信息</strong>（ id 的替代者）</li>
<li>应用在 html 标签上获取的是<strong>真实 DOM 元素</strong>，应用在组件标签上是<strong>组件实例对象（vc）</strong></li>
<li>使用方式：<ol>
<li>打标识：<code>&lt;h1 ref=&quot;xxx&quot;&gt;.....&lt;/h1&gt;</code> 或 <code>&lt;School ref=&quot;xxx&quot;&gt;&lt;/School&gt;</code></li>
<li>获取：<code>this.$refs.xxx</code></li>
</ol>
</li>
</ol>
</blockquote>
<h2 id="3-props-属性"><a href="#3-props-属性" class="headerlink" title="3.props 属性"></a>3.props 属性</h2><p>当我们要使用一个组件时，由于组件内部数据是指定好的，所以我们在使用的时候不能自定义数据，这就导致了一些问题，Vue 中可以指定 <code>props</code> 属性解决这一问题。</p>
<p>Student.vue（重点看 20 行）</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;!-- 组件的结构 --&gt;<br>  &lt;div class=&quot;demo&quot;&gt;<br>    &lt;h2&gt;学生姓名：&#123;&#123;name&#125;&#125;&lt;/h2&gt;<br>    &lt;h2&gt;学生年龄：&#123;&#123;age&#125;&#125;&lt;/h2&gt;<br>    &lt;h2&gt;学生性别：&#123;&#123;sex&#125;&#125;&lt;/h2&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>// 组件的交互相关的代码<br>export default &#123;<br>  name: &quot;Student&quot;,<br>  // 简单声明接收<br>  props: [&#x27;name&#x27;, &#x27;age&#x27;, &#x27;sex&#x27;]<br>&#125;<br>&lt;/script&gt;<br><br>&lt;style&gt;<br>/*组件的样式*/<br>.demo &#123;<br>  background: orange;<br>&#125;<br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>

<p>在 App.vue 中使用 Student 组件（注意 3,4,5 行）</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;div&gt;<br>    &lt;!-- 声明的时候就可以将自定义的数据传递进去 --&gt;<br>    &lt;!-- 注意由于 age 属性可能需要计算，所以使用 v-bind 绑定数据，这样引号内的数据就会被当成 js 解析--&gt;<br>    &lt;Student name=&quot;李四&quot; sex=&quot;男&quot; :age=&quot;20&quot;&gt;&lt;/Student&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>import Student from &quot;./components/Student&quot;;<br><br>export default &#123;<br>  name: &quot;App&quot;,<br>  components: &#123;Student&#125;<br>&#125;<br>&lt;/script&gt;<br></code></pre></td></tr></table></figure>

<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210804/image.1hokhh66ii74.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<p>但此时这些数据都是只读的，Vue 底层会监测你对 props 的修改，如果进行了修改，就会发出警告。</p>
<p>修改 Studnet.vue 中的组件结构</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;!-- 组件的结构 --&gt;<br>  &lt;div class=&quot;demo&quot;&gt;<br>    &lt;h2&gt;学生姓名：&#123;&#123;name&#125;&#125;&lt;/h2&gt;<br>    &lt;h2&gt;学生年龄：&#123;&#123;age&#125;&#125;&lt;/h2&gt;<br>    &lt;h2&gt;学生性别：&#123;&#123;sex&#125;&#125;&lt;/h2&gt;<br>    &lt;button @click=&quot;age++&quot;&gt;点我年龄+1&lt;/button&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br></code></pre></td></tr></table></figure>

<p>点击按钮，修改年龄，出现错误</p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210804/image.35f0to2sgya0.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<p>此时就可以在 data 或者计算属性中再配置一个数据，值的来源是 prop</p>
<p>Studnet.vue</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;!-- 组件的结构 --&gt;<br>  &lt;div class=&quot;demo&quot;&gt;<br>    &lt;h2&gt;学生姓名：&#123;&#123;name&#125;&#125;&lt;/h2&gt;<br>    &lt;h2&gt;学生年龄：&#123;&#123;myAge&#125;&#125;&lt;/h2&gt;<br>    &lt;h2&gt;学生性别：&#123;&#123;sex&#125;&#125;&lt;/h2&gt;<br>    &lt;!-- 使用 data 中指定的数据 --&gt; <br>    &lt;button @click=&quot;myAge++&quot;&gt;点我年龄+1&lt;/button&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>// 组件的交互相关的代码<br>export default &#123;<br>  name: &quot;School&quot;,<br>  data() &#123;<br>    return &#123;<br>      // 再指定一个数据  <br>      myAge: this.age<br>    &#125;<br>  &#125;,<br>  // 简单声明接收<br>  props: [&#x27;name&#x27;, &#x27;age&#x27;, &#x27;sex&#x27;]<br>&#125;<br>&lt;/script&gt;<br><br>&lt;style&gt;<br>/*组件的样式*/<br>.demo &#123;<br>  background: orange;<br>&#125;<br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>

<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210804/image.2i4p7o1a9qg0.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<p>prop 属性配置还有两种具体的写法</p>
<ol>
<li>```js<br>//接收的同时对数据进行类型限制<br>props:{<pre><code>name:String,
age:Number,
sex:String
</code></pre>
}<figure class="highlight dts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs dts"><br><span class="hljs-number">2.</span> ```js<br>   <span class="hljs-comment">// 接收的同时对数据：进行类型限制+默认值的指定+必要性的限制</span><br><span class="hljs-symbol">   props:</span> &#123;<br><span class="hljs-symbol">       name:</span> &#123;<br><span class="hljs-symbol">         type:</span> String,<span class="hljs-comment">// 类型是字符串</span><br><span class="hljs-symbol">         required:</span> true<span class="hljs-comment">// 属性是一定要写的</span><br>       &#125;,<br><span class="hljs-symbol">       age:</span> &#123;<br><span class="hljs-symbol">         type:</span> Number,<br><span class="hljs-symbol">         default:</span> <span class="hljs-number">99</span><span class="hljs-comment">// 属性可以不写，当属性没写的时候，使用默认值</span><br>       &#125;,<br><span class="hljs-symbol">       sex:</span> &#123;<br><span class="hljs-symbol">         type:</span> String,<br><span class="hljs-symbol">         required:</span> true<br>       &#125;<br>   &#125;<br></code></pre></td></tr></table></figure></li>
</ol>
<blockquote>
<p>总结：</p>
<ol>
<li><p>功能：让组件接收外部传过来的数据</p>
</li>
<li><p>传递数据：<code>&lt;Demo name=&quot;xxx&quot;/&gt;</code></p>
</li>
<li><p>接收数据：</p>
</li>
<li><p>第一种方式（只接收）：<code>props:[&#39;name&#39;] </code></p>
</li>
<li><p>第二种方式（限制类型）：<code>props:&#123;name:String&#125;</code></p>
</li>
<li><p>第三种方式（限制类型、限制必要性、指定默认值）：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs js">props:&#123;<br>	<span class="hljs-attr">name</span>:&#123;<br>        <span class="hljs-attr">type</span>:<span class="hljs-built_in">String</span>, <span class="hljs-comment">//类型</span><br>        <span class="hljs-attr">required</span>:<span class="hljs-literal">true</span>, <span class="hljs-comment">//必要性</span><br>        <span class="hljs-attr">default</span>:<span class="hljs-string">&#x27;老王&#x27;</span> <span class="hljs-comment">//默认值</span><br>	&#125;<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li><p><strong>备注：props 是只读的，Vue 底层会监测你对 props 的修改，如果进行了修改，就会发出警告，若业务需求确实需要修改，那么请复制 props 的内容到 data 中一份，然后去修改 data 中的数据。</strong></p>
</li>
</ol>
</blockquote>
<h2 id="4-mixin（混入）"><a href="#4-mixin（混入）" class="headerlink" title="4.mixin（混入）"></a>4.mixin（混入）</h2><p>当多个组件中存在同样的配置项时，可以将配置项提取出来混入一个对象，组件在使用时，引入就可以了。</p>
<p>在组件中都有一个点击显示名称的按钮</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;button @click=&quot;showName&quot;&gt;点我显示名称&lt;/button&gt;<br></code></pre></td></tr></table></figure>

<p>此时就可以在 mixin.js 中配置 methods</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">// 分别暴露</span><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> mixin = &#123;<br>    <span class="hljs-attr">methods</span>: &#123;<br>        <span class="hljs-function"><span class="hljs-title">showName</span>(<span class="hljs-params"></span>)</span> &#123;<br>            <span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">this</span>.name);<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>在组件中使用</p>
<p>Studnet.vue（重点在 12,25 行）</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;!-- 组件的结构 --&gt;<br>  &lt;div class=&quot;demo&quot;&gt;<br>    &lt;h2&gt;学生姓名：&#123;&#123;name&#125;&#125;&lt;/h2&gt;<br>    &lt;h2&gt;学生年龄：&#123;&#123;age&#125;&#125;&lt;/h2&gt;<br>    &lt;button @click=&quot;showName&quot;&gt;点我显示名称&lt;/button&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>// 导入 mixin<br>import &#123;mixin&#125; from &quot;@/mixin&quot;;<br><br><br>// 组件的交互相关的代码<br>export default &#123;<br>  name: &quot;Student&quot;,<br>  data() &#123;<br>    return &#123;<br>      name: &quot;张三&quot;,<br>      age: 20<br>    &#125;<br>  &#125;,<br>  // 使用 mixin<br>  mixins: [mixin]<br>&#125;<br>&lt;/script&gt;<br></code></pre></td></tr></table></figure>

<p>School.vue </p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;!-- 组件的结构 --&gt;<br>  &lt;div class=&quot;demo&quot;&gt;<br>    &lt;h2&gt;学校名称：&#123;&#123;name&#125;&#125;&lt;/h2&gt;<br>    &lt;h2&gt;学校地址：&#123;&#123;address&#125;&#125;&lt;/h2&gt;<br>    &lt;button @click=&quot;showName&quot;&gt;点我显示名称&lt;/button&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>// 导入 mixin<br>import &#123;mixin&#125; from &quot;@/mixin&quot;;<br><br>// 组件的交互相关的代码<br>export default &#123;<br>  name: &quot;School&quot;,<br>  data() &#123;<br>    return &#123;<br>      name: &quot;尚硅谷&quot;,<br>      address: &quot;北京&quot;<br>    &#125;<br>  &#125;,<br>  // 使用 mixin<br>  mixins: [mixin]<br>&#125;<br>&lt;/script&gt;<br></code></pre></td></tr></table></figure>

<p>运行</p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210804/image.72m86c0q7ig0.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<blockquote>
<p>总结：</p>
<ol>
<li><p>功能：可以把多个组件共用的配置提取成一个混入对象</p>
</li>
<li><p>使用方式：</p>
<p>第一步定义混合：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs js">&#123;<br>    <span class="hljs-function"><span class="hljs-title">data</span>(<span class="hljs-params"></span>)</span>&#123;....&#125;,<br>    <span class="hljs-attr">methods</span>:&#123;....&#125;<br>    ....<br>&#125;<br></code></pre></td></tr></table></figure>

<p>第二步使用混入：</p>
<p>​    全局混入：<code>Vue.mixin(xxx)</code><br>​    局部混入：<code>mixins:[&#39;xxx&#39;]    </code></p>
</li>
<li><p>当混入的内容和组件中原来的内容的有重复时，data 和 methods 中的数据使用组件指定的，声明周期函数中的内容都会执行。</p>
</li>
</ol>
</blockquote>
<h2 id="5-插件"><a href="#5-插件" class="headerlink" title="5.插件"></a>5.插件</h2><p>可以在 src 目录下配置一个 plugins.js 文件，在其中配置一次对 Vue 的增强功能。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> &#123;<br>    <span class="hljs-function"><span class="hljs-title">install</span>(<span class="hljs-params">a</span>)</span> &#123;<br>        <span class="hljs-comment">// 首先查看方法中会有什么参数传递进来</span><br>        <span class="hljs-built_in">console</span>.log(a)<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>在 main.js 中引入并使用插件</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;vue&quot;</span>;<br><span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;./App&quot;</span>;<br><span class="hljs-comment">// 引入插件</span><br><span class="hljs-keyword">import</span> plugins <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;./plugins&quot;</span>;<br><br>Vue.config.productionTip = <span class="hljs-literal">false</span><br><span class="hljs-comment">// 使用插件</span><br>Vue.use(plugins)<br><br><span class="hljs-keyword">new</span> Vue(&#123;<br>    <span class="hljs-attr">el</span>: <span class="hljs-string">&#x27;#app&#x27;</span>,<br>    <span class="hljs-attr">render</span>: <span class="hljs-function"><span class="hljs-params">h</span> =&gt;</span> h(App)<br>&#125;)<br></code></pre></td></tr></table></figure>

<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210804/image.5h6z41iwfow0.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<p>通过测试发现 install 方法中传入的参数是 Vue 构造方法，因此可以在插件进行一些 Vue 的全局配置，增强 Vue 的功能。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> &#123;<br>    <span class="hljs-function"><span class="hljs-title">install</span>(<span class="hljs-params">Vue</span>)</span>&#123;<br>        <span class="hljs-comment">// 全局过滤器</span><br>        Vue.filter(<span class="hljs-string">&#x27;mySlice&#x27;</span>,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>)</span>&#123;<br>            <span class="hljs-keyword">return</span> value.slice(<span class="hljs-number">0</span>,<span class="hljs-number">4</span>)<br>        &#125;)<br><br>        <span class="hljs-comment">//定义全局指令</span><br>        Vue.directive(<span class="hljs-string">&#x27;fbind&#x27;</span>,&#123;<br>            <span class="hljs-comment">//指令与元素成功绑定时（一上来）</span><br>            <span class="hljs-function"><span class="hljs-title">bind</span>(<span class="hljs-params">element,binding</span>)</span>&#123;<br>                element.value = binding.value<br>            &#125;,<br>            <span class="hljs-comment">//指令所在元素被插入页面时</span><br>            <span class="hljs-function"><span class="hljs-title">inserted</span>(<span class="hljs-params">element</span>)</span>&#123;<br>                element.focus()<br>            &#125;,<br>            <span class="hljs-comment">//指令所在的模板被重新解析时</span><br>            <span class="hljs-function"><span class="hljs-title">update</span>(<span class="hljs-params">element,binding</span>)</span>&#123;<br>                element.value = binding.value<br>            &#125;<br>        &#125;)<br><br>        <span class="hljs-comment">//定义混入</span><br>        Vue.mixin(&#123;<br>            <span class="hljs-function"><span class="hljs-title">data</span>(<span class="hljs-params"></span>)</span> &#123;<br>                <span class="hljs-keyword">return</span> &#123;<br>                    <span class="hljs-attr">x</span>:<span class="hljs-number">100</span>,<br>                    <span class="hljs-attr">y</span>:<span class="hljs-number">200</span><br>                &#125;<br>            &#125;,<br>        &#125;)<br><br>        <span class="hljs-comment">//给Vue原型上添加一个方法（vm和vc就都能用了）</span><br>        Vue.prototype.hello = <span class="hljs-function">()=&gt;</span>&#123;alert(<span class="hljs-string">&#x27;你好啊&#x27;</span>)&#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p> 同样在 mian.js 中引入并通过 <code>Vue.use(插件)</code> 就可以使用插件了。</p>
<blockquote>
<p>总结：</p>
<ol>
<li><p>功能：用于增强 Vue</p>
</li>
<li><p>本质：包含 install 方法的一个对象，install 的第一个参数是 Vue，第二个以后的参数是插件使用者传递的数据。</p>
</li>
<li><p>定义插件：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs js">对象 &#123;<br>    install = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">Vue, options</span>) </span>&#123;<br>        <span class="hljs-comment">// 1. 添加全局过滤器</span><br>        Vue.filter(....)<br><br>        <span class="hljs-comment">// 2. 添加全局指令</span><br>        Vue.directive(....)<br><br>        <span class="hljs-comment">// 3. 配置全局混入(合)</span><br>        Vue.mixin(....)<br><br>        <span class="hljs-comment">// 4. 添加实例方法</span><br>        Vue.prototype.$myMethod = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>&#123;...&#125;<br>        Vue.prototype.$myProperty = xxxx<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li><p>使用插件：<code>Vue.use()</code></p>
</li>
</ol>
</blockquote>
<h2 id="6-scoped-样式"><a href="#6-scoped-样式" class="headerlink" title="6.scoped 样式"></a>6.scoped 样式</h2><p>每个组件中的样式是写在 <code>&lt;style&gt;&lt;/style&gt;</code> 标签中的，但是当组件整合在一起的时候，所有的样式都是在一起统一使用的，这样就会造成一个问题，可能会有样式名一样，此时，会根据组件引入的顺序，依次覆盖已存在的同名样式，这样就会造成样式使用错误。</p>
<p>因此可以在 style 标签中添加一个 scoped 标志，即 <code>&lt;style scoped&gt;&lt;/style&gt;</code> ，此时每个样式之会在当前组件中使用。</p>
<p>Student.vue</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;!-- 组件的结构 --&gt;<br>  &lt;div class=&quot;demo&quot;&gt;<br>    &lt;h2&gt;学生姓名：&#123;&#123;name&#125;&#125;&lt;/h2&gt;<br>    &lt;h2&gt;学生年龄：&#123;&#123;age&#125;&#125;&lt;/h2&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>// 组件的交互相关的代码<br>export default &#123;<br>  name: &quot;Student&quot;,<br>  data() &#123;<br>    return &#123;<br>      name: &quot;张三&quot;,<br>      age: 20<br>    &#125;<br>  &#125;<br>&#125;<br>&lt;/script&gt;<br><br>&lt;style scoped&gt;<br>.demo &#123;<br>  background: pink;<br>&#125;<br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>

<p>School.vue</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;!-- 组件的结构 --&gt;<br>  &lt;div class=&quot;demo&quot;&gt;<br>    &lt;h2&gt;学校名称：&#123;&#123;name&#125;&#125;&lt;/h2&gt;<br>    &lt;h2&gt;学校地址：&#123;&#123;address&#125;&#125;&lt;/h2&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>// 组件的交互相关的代码<br>export default &#123;<br>  name: &quot;School&quot;,<br>  data() &#123;<br>    return &#123;<br>      name: &quot;尚硅谷&quot;,<br>      address: &quot;北京&quot;<br>    &#125;<br>  &#125;<br>&#125;<br>&lt;/script&gt;<br><br>&lt;style scoped&gt;<br>  .demo &#123;<br>    background: orange;<br>  &#125;<br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>

<p>测试</p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210804/image.6s0a9o10vhs0.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<h2 id="7-TodoList-案例"><a href="#7-TodoList-案例" class="headerlink" title="7.TodoList 案例"></a>7.TodoList 案例</h2><p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210804/image.1qqz6gxu096o.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<ol>
<li><p>组件化编码流程：</p>
<p>​    (1).拆分静态组件：组件要按照功能点拆分，命名不要与 html 元素冲突。</p>
<p>​    (2).实现动态组件：考虑好数据的存放位置，数据是一个组件在用，还是一些组件在用：</p>
<p>​            1).一个组件在用：放在组件自身即可。</p>
<p>​            2). 一些组件在用：放在他们共同的父组件上（<span style="color:red">状态提升</span>）。</p>
<p>​    (3).实现交互：从绑定事件开始。</p>
</li>
<li><p>props 适用于：</p>
<p>​    (1).父组件 ==&gt; 子组件 通信</p>
<p>​    (2).子组件 ==&gt; 父组件 通信（要求父先给子一个函数）</p>
</li>
<li><p>使用 v-model 时要切记：v-model 绑定的值不能是 props 传过来的值，因为 props 是不可以修改的！</p>
</li>
<li><p>props 传过来的若是对象类型的值，修改对象中的属性时 Vue 不会报错，但不推荐这样做。</p>
</li>
</ol>
<h3 id="App-vue"><a href="#App-vue" class="headerlink" title="App.vue"></a><code>App.vue</code></h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;div id=&quot;root&quot;&gt;<br>    &lt;div class=&quot;todo-container&quot;&gt;<br>      &lt;div class=&quot;todo-wrap&quot;&gt;<br>        &lt;TodoHeader :askForTodoItem=&quot;askForTodoItem&quot;&gt;&lt;/TodoHeader&gt;<br>        &lt;TodoList :todoList=&quot;todoList&quot; :changeCheck=&quot;changeCheck&quot; :deleteTodoItem=&quot;deleteTodoItem&quot;&gt;&lt;/TodoList&gt;<br>        &lt;TodoFooter :todoList=&quot;todoList&quot; :selectAll=&quot;selectAll&quot; :clearCompletedEvent=&quot;clearCompletedEvent&quot;&gt;&lt;/TodoFooter&gt;<br>      &lt;/div&gt;<br>    &lt;/div&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>// 引入组件<br>import TodoHeader from &quot;./components/TodoHeader&quot;;<br>import TodoList from &quot;./components/TodoList&quot;;<br>import TodoFooter from &quot;./components/TodoFooter&quot;;<br>import &#123;nanoid&#125; from &quot;nanoid&quot;;<br><br>export default &#123;<br>  name: &quot;App&quot;,<br>  components:&#123;TodoHeader, TodoList, TodoFooter&#125;,<br>  data() &#123;<br>    return &#123;<br>      todoList: [<br>        &#123;id: nanoid(), eventName: &quot;吃饭&quot;, complete: true&#125;,<br>        &#123;id: nanoid(), eventName: &quot;睡觉&quot;, complete: false&#125;,<br>        &#123;id: nanoid(), eventName: &quot;玩手机&quot;, complete: true&#125;,<br>      ]<br>    &#125;<br>  &#125;,<br>  methods: &#123;<br>    /**<br>     * 向 TodoHeader 询问要一个 todoItem 对象<br>     * @param todoItem<br>     */<br>    askForTodoItem(todoItem) &#123;<br>      // 将 todoItem 添加到 todoList 最前面<br>      this.todoList.unshift(todoItem);<br>    &#125;,<br>    /**<br>     * 修改 todoList 中的选中<br>     * @param id 选中的 todoItem 的 id<br>     */<br>    changeCheck(id) &#123;<br>      // 编历 todoList<br>      this.todoList.forEach((todoItem) =&gt; &#123;<br>        // todoItem.complete 取反<br>        if(todoItem.id === id) &#123;<br>          todoItem.complete = !todoItem.complete;<br>        &#125;<br>      &#125;)<br>    &#125;,<br>    /**<br>     * 根据 todoItem 的 id 删除元素<br>     * @param id<br>     */<br>    deleteTodoItem(id) &#123;<br>      if(confirm(&quot;确定要删除吗？&quot;)) &#123;<br>        this.todoList = this.todoList.filter((todoItem) =&gt; &#123;<br>          return todoItem.id !== id;<br>        &#125;)<br>      &#125;<br>    &#125;,<br>    /**<br>     * 选中 或 取消选中所有<br>     */<br>    selectAll(complete) &#123;<br>      this.todoList.forEach((todoItem) =&gt; &#123;<br>        todoItem.complete = complete;<br>      &#125;)<br>    &#125;,<br>    /**<br>     * 清除所有已完成的事件<br>     */<br>    clearCompletedEvent() &#123;<br>      if (confirm(&quot;确定要删除也完成的项目吗&quot;)) &#123;<br>        this.todoList = this.todoList.filter((todoItem) =&gt; &#123;<br>          return !todoItem.complete;<br>        &#125;)<br>      &#125;<br>    &#125;<br>  &#125;<br>&#125;<br>&lt;/script&gt;<br><br>&lt;style&gt;<br>  /*base*/<br>  body &#123;<br>    background: #fff;<br>  &#125;<br><br>  .btn &#123;<br>    display: inline-block;<br>    padding: 4px 12px;<br>    margin-bottom: 0;<br>    font-size: 14px;<br>    line-height: 20px;<br>    text-align: center;<br>    vertical-align: middle;<br>    cursor: pointer;<br>    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);<br>    border-radius: 4px;<br>  &#125;<br><br>  .btn-danger &#123;<br>    color: #fff;<br>    background-color: #da4f49;<br>    border: 1px solid #bd362f;<br>  &#125;<br><br>  .btn-danger:hover &#123;<br>    color: #fff;<br>    background-color: #bd362f;<br>  &#125;<br><br>  .btn:focus &#123;<br>    outline: none;<br>  &#125;<br><br>  .todo-container &#123;<br>    width: 600px;<br>    margin: 0 auto;<br>  &#125;<br><br>  .todo-container .todo-wrap &#123;<br>    padding: 10px;<br>    border: 1px solid #ddd;<br>    border-radius: 5px;<br>  &#125;<br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>

<h3 id="TodoHeader-vue"><a href="#TodoHeader-vue" class="headerlink" title="TodoHeader.vue"></a><code>TodoHeader.vue</code></h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;div class=&quot;todo-header&quot;&gt;<br>    &lt;input type=&quot;text&quot; placeholder=&quot;请输入你的任务名称，按回车键确认&quot; v-model=&quot;eventName&quot; @keyup.enter=&quot;addTodoItem&quot;/&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br><br>import &#123;nanoid&#125; from &quot;nanoid&quot;;<br><br>export default &#123;<br>  name: &quot;TodoHeader&quot;,<br>  props: [&#x27;askForTodoItem&#x27;],<br>  data() &#123;<br>    return &#123;<br>      eventName: &#x27;&#x27;<br>    &#125;<br>  &#125;,<br>  methods: &#123;<br>    addTodoItem() &#123;<br>      // 校验输入的数据<br>      if(!this.eventName.trim()) return alert(&quot;输入不能为空&quot;);<br>      // 将 eventName 封装成一个 todoItem<br>      const todoItem = &#123;id: nanoid(), eventName: this.eventName, complete: false&#125;;<br>      // 将 todoItem 对象传递给 App，通过 App 将 todoItem 添加到 todoList<br>      this.askForTodoItem(todoItem);<br>      // 清空文本框输入<br>      this.eventName = &quot;&quot;;<br>    &#125;<br>  &#125;<br>&#125;<br>&lt;/script&gt;<br><br>&lt;style scoped&gt;<br>  /*header*/<br>  .todo-header input &#123;<br>    width: 560px;<br>    height: 28px;<br>    font-size: 14px;<br>    border: 1px solid #ccc;<br>    border-radius: 4px;<br>    padding: 4px 7px;<br>  &#125;<br><br>  .todo-header input:focus &#123;<br>    outline: none;<br>    border-color: rgba(82, 168, 236, 0.8);<br>    box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);<br>  &#125;<br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>

<h3 id="TodoList-vue"><a href="#TodoList-vue" class="headerlink" title="TodoList.vue"></a><code>TodoList.vue</code></h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;ul class=&quot;todo-main&quot;&gt;<br>    &lt;TodoItem<br>        v-for=&quot;todoItem in todoList&quot;<br>        :todoItem=&quot;todoItem&quot;<br>        :key=&quot;todoItem.id&quot;<br>        :changeCheck=&quot;changeCheck&quot;<br>        :deleteTodoItem=&quot;deleteTodoItem&quot;<br>    &gt;&lt;/TodoItem&gt;<br>  &lt;/ul&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>// 引入 TodoItem 组件<br>import TodoItem from &quot;./TodoItem&quot;;<br><br><br>export default &#123;<br>  name: &quot;TodoList&quot;,<br>  components:&#123;TodoItem&#125;,<br>  props: [&#x27;todoList&#x27;, &#x27;changeCheck&#x27;, &#x27;deleteTodoItem&#x27;]<br>&#125;<br>&lt;/script&gt;<br><br>&lt;style scoped&gt;<br>  /*main*/<br>  .todo-main &#123;<br>    margin-left: 0px;<br>    border: 1px solid #ddd;<br>    border-radius: 2px;<br>    padding: 0px;<br>  &#125;<br><br>  .todo-empty &#123;<br>    height: 40px;<br>    line-height: 40px;<br>    border: 1px solid #ddd;<br>    border-radius: 2px;<br>    padding-left: 5px;<br>    margin-top: 10px;<br>  &#125;<br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>

<h3 id="TodoItem-vue"><a href="#TodoItem-vue" class="headerlink" title="TodoItem.vue"></a><code>TodoItem.vue</code></h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;li&gt;<br>    &lt;label&gt;<br>      &lt;input type=&quot;checkbox&quot; :checked=&quot;todoItem.complete&quot; @change=&quot;handleChangeCheck(todoItem.id)&quot;/&gt;<br>      &lt;!-- 如下代码也能实现功能，但是不太推荐，因为有点违反原则，因为修改了 props --&gt;<br>      &lt;!-- &lt;input type=&quot;checkbox&quot; v-model=&quot;todoItem.complete&quot;/&gt; --&gt;<br>      &lt;span&gt;&#123;&#123;todoItem.eventName&#125;&#125;&lt;/span&gt;<br>    &lt;/label&gt;<br>    &lt;button class=&quot;btn btn-danger&quot; @click=&quot;handleDeleteTodoItem(todoItem.id)&quot;&gt;删除&lt;/button&gt;<br>  &lt;/li&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>export default &#123;<br>  name: &quot;TodoItem&quot;,<br>  props: [&#x27;todoItem&#x27;, &#x27;changeCheck&#x27;, &#x27;deleteTodoItem&#x27;],<br>  methods: &#123;<br>    handleChangeCheck(id) &#123;<br>      // 通知 App 组件调用 changeCheck 函数改变选择<br>      this.changeCheck(id);<br>    &#125;,<br>    handleDeleteTodoItem(id) &#123;<br>      // 通知 App 组件调用 deleteTodoItem 函数删除<br>      this.deleteTodoItem(id);<br>    &#125;<br>  &#125;<br>&#125;<br>&lt;/script&gt;<br><br>&lt;style scoped&gt;<br>  /*item*/<br>  li &#123;<br>    list-style: none;<br>    height: 36px;<br>    line-height: 36px;<br>    padding: 0 5px;<br>    border-bottom: 1px solid #ddd;<br>  &#125;<br><br>  li label &#123;<br>    float: left;<br>    cursor: pointer;<br>  &#125;<br><br>  li label li input &#123;<br>    vertical-align: middle;<br>    margin-right: 6px;<br>    position: relative;<br>    top: -1px;<br>  &#125;<br><br>  li button &#123;<br>    float: right;<br>    display: none;<br>    margin-top: 3px;<br>  &#125;<br><br>  li:before &#123;<br>    content: initial;<br>  &#125;<br><br>  li:last-child &#123;<br>    border-bottom: none;<br>  &#125;<br><br>  li:hover &#123;<br>    background: #dddddd;<br>  &#125;<br><br>  li:hover button &#123;<br>    display: block;<br>  &#125;<br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>

<h3 id="TodoFooter-vue"><a href="#TodoFooter-vue" class="headerlink" title="TodoFooter.vue"></a><code>TodoFooter.vue</code></h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;div class=&quot;todo-footer&quot; v-show=&quot;totalCount&quot;&gt;<br>    &lt;label&gt;<br>      &lt;input type=&quot;checkbox&quot; v-model=&quot;isAll&quot;/&gt;<br>    &lt;/label&gt;<br>    &lt;span&gt;<br>          &lt;span&gt;已完成 &#123;&#123;completedCount&#125;&#125;&lt;/span&gt; / 全部 &#123;&#123;totalCount&#125;&#125;<br>    &lt;/span&gt;<br>    &lt;button class=&quot;btn btn-danger&quot; @click=&quot;handleClearCompletedEvent&quot;&gt;清除已完成任务&lt;/button&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>export default &#123;<br>  name: &quot;TodoFooter&quot;,<br>  props: [&#x27;todoList&#x27;, &#x27;selectAll&#x27;, &#x27;clearCompletedEvent&#x27;],<br>  computed: &#123;<br>    // todoList 元素个数<br>    totalCount() &#123;<br>      return this.todoList.length;<br>    &#125;,<br>    // todoList 中 complete 为 true 的元素个数<br>    completedCount() &#123;<br>      // 使用循环编历方法做条件统计<br>      /*let count = 0;<br>      this.todoList.forEach((todoItem) =&gt; &#123;<br>        if (todoItem.complete) count++;<br>      &#125;)<br>      return count;*/<br><br>      // 使用reduce方法做条件统计<br>      return this.todoList.reduce((count,current)=&gt;&#123;<br>        return count + (current.complete ? 1 : 0)<br>      &#125;,0)<br>    &#125;,<br>    // 判断选中的和总数是否相同<br>    isAll: &#123;<br>      get() &#123;<br>        return this.totalCount === this.completedCount &amp;&amp; this.totalCount &gt; 0;<br>      &#125;,<br>      set(value) &#123;<br>        this.selectAll(value);<br>      &#125;<br><br>    &#125;<br>  &#125;,<br>  methods: &#123;<br>    handleClearCompletedEvent() &#123;<br>      this.clearCompletedEvent();<br>    &#125;<br>  &#125;<br>&#125;<br>&lt;/script&gt;<br><br>&lt;style scoped&gt;<br>  /*footer*/<br>  .todo-footer &#123;<br>    height: 40px;<br>    line-height: 40px;<br>    padding-left: 6px;<br>    margin-top: 5px;<br>  &#125;<br><br>  .todo-footer label &#123;<br>    display: inline-block;<br>    margin-right: 20px;<br>    cursor: pointer;<br>  &#125;<br><br>  .todo-footer label input &#123;<br>    position: relative;<br>    top: -1px;<br>    vertical-align: middle;<br>    margin-right: 5px;<br>  &#125;<br><br>  .todo-footer button &#123;<br>    float: right;<br>    margin-top: 5px;<br>  &#125;<br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>





<h2 id="8-浏览器本地存储"><a href="#8-浏览器本地存储" class="headerlink" title="8.浏览器本地存储"></a>8.浏览器本地存储</h2><h3 id="8-1-localStorage"><a href="#8-1-localStorage" class="headerlink" title="8.1 localStorage"></a>8.1 localStorage</h3><p>将数据保存在本地，即使浏览器关闭后数据也能存在，之后还能再读取。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">&quot;en&quot;</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">&quot;UTF-8&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>localStorage<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>localStorage<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">&quot;saveData()&quot;</span>&gt;</span>保存数据<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">&quot;readData()&quot;</span>&gt;</span>读取 key 为 person 的数据<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">&quot;deleteData()&quot;</span>&gt;</span>删除 key 为 address 的数据<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">&quot;deleteAllData()&quot;</span>&gt;</span>清除所有数据<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br><br>    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;text/javascript&quot;</span>&gt;</span><span class="javascript"></span><br><span class="javascript">        <span class="hljs-comment">/**</span></span><br><span class="hljs-comment"><span class="javascript">         * 保存两个数据到本地</span></span><br><span class="hljs-comment"><span class="javascript">         */</span></span><br><span class="javascript">        <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">saveData</span>(<span class="hljs-params"></span>) </span>&#123;</span><br><span class="javascript">            <span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">&quot;address&quot;</span>, <span class="hljs-string">&quot;北京&quot;</span>);</span><br><span class="javascript">            <span class="hljs-keyword">let</span> person = &#123;<span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;张三&#x27;</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">20</span>, <span class="hljs-attr">sex</span>: <span class="hljs-string">&quot;男&quot;</span>&#125;;</span><br><span class="javascript">            <span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">&quot;person&quot;</span>, <span class="hljs-built_in">JSON</span>.stringify(person),);</span><br><span class="javascript">        &#125;</span><br><span class="javascript"></span><br><span class="javascript">        <span class="hljs-comment">/**</span></span><br><span class="hljs-comment"><span class="javascript">         * 获取本地数据</span></span><br><span class="hljs-comment"><span class="javascript">         */</span></span><br><span class="javascript">        <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readData</span>(<span class="hljs-params"></span>) </span>&#123;</span><br><span class="javascript">            <span class="hljs-keyword">let</span> person = <span class="hljs-built_in">JSON</span>.parse(<span class="hljs-built_in">localStorage</span>.getItem(<span class="hljs-string">&quot;person&quot;</span>));</span><br><span class="javascript">            <span class="hljs-built_in">console</span>.log(person);</span><br><span class="javascript">        &#125;</span><br><span class="javascript"></span><br><span class="javascript">        <span class="hljs-comment">/**</span></span><br><span class="hljs-comment"><span class="javascript">         * 移除本地一条数据</span></span><br><span class="hljs-comment"><span class="javascript">         */</span></span><br><span class="javascript">        <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">deleteData</span>(<span class="hljs-params"></span>) </span>&#123;</span><br><span class="javascript">            <span class="hljs-built_in">localStorage</span>.removeItem(<span class="hljs-string">&quot;address&quot;</span>);</span><br><span class="javascript">        &#125;</span><br><span class="javascript"></span><br><span class="javascript">        <span class="hljs-comment">/**</span></span><br><span class="hljs-comment"><span class="javascript">         * 移除本地所有数据</span></span><br><span class="hljs-comment"><span class="javascript">         */</span></span><br><span class="javascript">        <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">deleteAllData</span>(<span class="hljs-params"></span>) </span>&#123;</span><br><span class="javascript">            <span class="hljs-built_in">localStorage</span>.clear();</span><br><span class="javascript">        &#125;</span><br><span class="javascript">    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>本地数据保存在</p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210805/image.3w4x1ekb3kq0.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<h3 id="8-2-sessionStorage"><a href="#8-2-sessionStorage" class="headerlink" title="8.2 sessionStorage"></a>8.2 sessionStorage</h3><p>将数据保存在浏览器内存中，当浏览器关闭后，会话断掉，数据就丢失。使用方法和 <code>localStorage</code> 一模一样。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">&quot;en&quot;</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">&quot;UTF-8&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>sessionStorage<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>sessionStorage<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">&quot;saveData()&quot;</span>&gt;</span>保存数据<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">&quot;readData()&quot;</span>&gt;</span>读取 key 为 person 的数据<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">&quot;deleteData()&quot;</span>&gt;</span>删除 key 为 address 的数据<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">&quot;deleteAllData()&quot;</span>&gt;</span>清除所有数据<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br><br><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;text/javascript&quot;</span>&gt;</span><span class="javascript"></span><br><span class="javascript">    <span class="hljs-comment">/**</span></span><br><span class="hljs-comment"><span class="javascript">     * 保存两个数据到本地</span></span><br><span class="hljs-comment"><span class="javascript">     */</span></span><br><span class="javascript">    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">saveData</span>(<span class="hljs-params"></span>) </span>&#123;</span><br><span class="javascript">        sessionStorage.setItem(<span class="hljs-string">&quot;address&quot;</span>, <span class="hljs-string">&quot;北京&quot;</span>);</span><br><span class="javascript">        <span class="hljs-keyword">let</span> person = &#123;<span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;张三&#x27;</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">20</span>, <span class="hljs-attr">sex</span>: <span class="hljs-string">&quot;男&quot;</span>&#125;;</span><br><span class="javascript">        sessionStorage.setItem(<span class="hljs-string">&quot;person&quot;</span>, <span class="hljs-built_in">JSON</span>.stringify(person),);</span><br><span class="javascript">    &#125;</span><br><span class="javascript"></span><br><span class="javascript">    <span class="hljs-comment">/**</span></span><br><span class="hljs-comment"><span class="javascript">     * 获取本地数据</span></span><br><span class="hljs-comment"><span class="javascript">     */</span></span><br><span class="javascript">    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readData</span>(<span class="hljs-params"></span>) </span>&#123;</span><br><span class="javascript">        <span class="hljs-keyword">let</span> person = <span class="hljs-built_in">JSON</span>.parse(sessionStorage.getItem(<span class="hljs-string">&quot;person&quot;</span>));</span><br><span class="javascript">        <span class="hljs-built_in">console</span>.log(person);</span><br><span class="javascript">    &#125;</span><br><span class="javascript"></span><br><span class="javascript">    <span class="hljs-comment">/**</span></span><br><span class="hljs-comment"><span class="javascript">     * 移除本地一条数据</span></span><br><span class="hljs-comment"><span class="javascript">     */</span></span><br><span class="javascript">    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">deleteData</span>(<span class="hljs-params"></span>) </span>&#123;</span><br><span class="javascript">        sessionStorage.removeItem(<span class="hljs-string">&quot;address&quot;</span>);</span><br><span class="javascript">    &#125;</span><br><span class="javascript"></span><br><span class="javascript">    <span class="hljs-comment">/**</span></span><br><span class="hljs-comment"><span class="javascript">     * 移除本地所有数据</span></span><br><span class="hljs-comment"><span class="javascript">     */</span></span><br><span class="javascript">    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">deleteAllData</span>(<span class="hljs-params"></span>) </span>&#123;</span><br><span class="javascript">        sessionStorage.clear();</span><br><span class="javascript">    &#125;</span><br><span class="javascript"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210805/image.mjunv1yj4mo.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<blockquote>
<p>总结 <code>webStorage</code>：</p>
<ol>
<li><p>存储内容大小一般支持 5MB 左右（不同浏览器可能还不一样）</p>
</li>
<li><p>浏览器端通过 <code>Window.sessionStorage</code> 和 <code>Window.localStorage</code> 属性来实现本地存储机制。</p>
</li>
<li><p>相关API：</p>
<ol>
<li><p><code>xxxxxStorage.setItem(&#39;key&#39;, &#39;value&#39;);</code><br>该方法接受一个键和值作为参数，会把键值对添加到存储中，如果键名存在，则更新其对应的值。</p>
</li>
<li><p><code>xxxxxStorage.getItem(&#39;person&#39;);</code></p>
<p>该方法接受一个键名作为参数，返回键名对应的值。</p>
</li>
<li><p><code>xxxxxStorage.removeItem(&#39;key&#39;);</code></p>
<p>该方法接受一个键名作为参数，并把该键名从存储中删除。</p>
</li>
<li><p><code> xxxxxStorage.clear()</code></p>
<p>该方法会清空存储中的所有数据。</p>
</li>
</ol>
</li>
<li><p>备注：</p>
<ol>
<li>SessionStorage 存储的内容会随着浏览器窗口关闭而消失。</li>
<li>LocalStorage 存储的内容，需要手动清除才会消失。</li>
<li><code>xxxxxStorage.getItem(xxx)</code>如果 xxx 对应的 value 获取不到，那么 getItem 的返回值是 null。</li>
<li><code>JSON.parse(null)</code>的结果依然是 null。</li>
</ol>
</li>
</ol>
</blockquote>
<h2 id="9-改造-TodoList-案例数据为本地存储"><a href="#9-改造-TodoList-案例数据为本地存储" class="headerlink" title="9.改造 TodoList 案例数据为本地存储"></a>9.改造 TodoList 案例数据为本地存储</h2><p>之前的初始数据都是我们自己先写好的，并且每次刷新页面后，设置的数据都会丢失。</p>
<p>现在我们使用 <code>localStorage</code> 将数据保存到浏览器，每次初始化时都从浏览器中获取数据。</p>
<p>在 App.vue 中添加一个监视器，监视 todoList 的变化，一变化就将数据重新保存。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">// 添加一个监视器，监视 todoList 的变化，只要数据一变化，就将数据保存到本地</span><br><span class="hljs-attr">watch</span>: &#123;<br>  <span class="hljs-attr">todoList</span>: &#123;<br>    <span class="hljs-attr">deep</span>: <span class="hljs-literal">true</span>,<br>    <span class="hljs-function"><span class="hljs-title">handler</span>(<span class="hljs-params"></span>)</span> &#123;<br>      <span class="hljs-comment">// 将数据保存到本地</span><br>      <span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">&quot;todoList&quot;</span>, <span class="hljs-built_in">JSON</span>.stringify(<span class="hljs-built_in">this</span>.todoList));<br>    &#125;<br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>修改 data 中的 todoList 属性的数据来源，来源为浏览器</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-function"><span class="hljs-title">data</span>(<span class="hljs-params"></span>)</span> &#123;<br>  <span class="hljs-keyword">return</span> &#123;<br>    <span class="hljs-comment">// 从浏览器获取数据，如果没有找到，就为空数组</span><br>    <span class="hljs-attr">todoList</span>: <span class="hljs-built_in">JSON</span>.parse(<span class="hljs-built_in">localStorage</span>.getItem(<span class="hljs-string">&quot;todoList&quot;</span>)) || []<br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210805/image.653qwz54co00.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<h2 id="10-组件自定义事件"><a href="#10-组件自定义事件" class="headerlink" title="10.组件自定义事件"></a>10.组件自定义事件</h2><p>之前在进行组件之间的通讯是，我们使用的办法是父组件将一个以 prop 的形式传递给子组件，子组件可以调用这个方法将自己的数据传递给父组件。其实这样会挺麻烦的。</p>
<p>我们可以使用组件自定义事件来完成组件之间的通信。</p>
<h3 id="10-1-第一种写法"><a href="#10-1-第一种写法" class="headerlink" title="10.1 第一种写法"></a>10.1 第一种写法</h3><p>在父组件中使用 <code>@ 或 v-on</code> 绑定事件，在子组件中使用 <code>vc.$emit(&quot;事件名&quot;, 传递数据)</code> 触发组件实例身上事件，此时会调用自定义事件绑定的回调函数，回调函数的参数就是传递过来的数据，因此父组件中就获取到了子组件的数据了。 </p>
<p>Student.vue（重点在 21 行）</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br> &lt;div class=&quot;student&quot;&gt;<br>  &lt;h2&gt;学生姓名：&#123;&#123;name&#125;&#125;&lt;/h2&gt;<br>  &lt;h2&gt;学生性别：&#123;&#123;sex&#125;&#125;&lt;/h2&gt;<br>    &lt;button @click=&quot;sendStudentName&quot;&gt;发送学生姓名&lt;/button&gt;<br> &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br> export default &#123;<br>  name:&#x27;Student&#x27;,<br>  data() &#123;<br>   return &#123;<br>    name:&#x27;张三&#x27;,<br>    sex:&#x27;男&#x27;,<br>   &#125;<br>  &#125;,<br>    methods: &#123;<br>      sendStudentName() &#123;<br>        // 触发 Student 组件实例身上的 getStudentName 事件<br>        this.$emit(&quot;getStudentName&quot;, this.name);<br>      &#125;<br>    &#125;<br> &#125;<br>&lt;/script&gt;<br><br>&lt;style scoped&gt;<br> .student&#123;<br>  background-color: pink;<br>  padding: 5px;<br>  margin-top: 30px;<br> &#125;<br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>

<p>App.vue（重点在 4、21-23 行 ）</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br> &lt;div class=&quot;app&quot;&gt;<br>  &lt;h1&gt;&#123;&#123;msg&#125;&#125; 学生姓名是:&#123;&#123;studentName&#125;&#125;&lt;/h1&gt;<br>    &lt;Student @getStudentName=&quot;getStudentName&quot;&gt;&lt;/Student&gt;<br> &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br> import Student from &#x27;./components/Student&#x27;<br><br> export default &#123;<br>  name:&#x27;App&#x27;,<br>  components:&#123;Student&#125;,<br>  data() &#123;<br>   return &#123;<br>    msg:&#x27;你好啊!&#x27;,<br>    studentName:&#x27;&#x27;<br>   &#125;<br>  &#125;,<br>    methods: &#123;<br>      getStudentName(name) &#123;<br>        this.studentName = name;<br>      &#125;<br>    &#125;<br> &#125;<br>&lt;/script&gt;<br><br>&lt;style scoped&gt;<br> .app&#123;<br>  background-color: gray;<br>  padding: 5px;<br> &#125;<br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>



<h3 id="10-2-第二种写法"><a href="#10-2-第二种写法" class="headerlink" title="10.2 第二种写法"></a>10.2 第二种写法</h3><p>使用 <code>ref=&#39;xxx&#39;</code> 属性在子组件实例上，父组件中就可以通过 <code>this.$refs.xxx.$on(&#39;事件名&#39;, 回调函数)</code>    </p>
<p>在挂载完成后，将自定义事件和回调函数绑定，当自定义事件触发，回调函数就收到数据并执行</p>
<p>App.vue（重点在 25-27）</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br> &lt;div class=&quot;app&quot;&gt;<br>  &lt;h1&gt;&#123;&#123;msg&#125;&#125; 学生姓名是:&#123;&#123;studentName&#125;&#125;&lt;/h1&gt;<br>    &lt;Student ref=&quot;student&quot;&gt;&lt;/Student&gt;<br> &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br> import Student from &#x27;./components/Student&#x27;<br><br> export default &#123;<br>  name:&#x27;App&#x27;,<br>  components:&#123;Student&#125;,<br>  data() &#123;<br>   return &#123;<br>    msg:&#x27;你好啊!&#x27;,<br>    studentName:&#x27;&#x27;<br>   &#125;<br>  &#125;,<br>    methods: &#123;<br>      getStudentName(name) &#123;<br>        this.studentName = name;<br>      &#125;<br>    &#125;,<br>    mounted() &#123;<br>    	this.$refs.student.$on(&quot;getStudentName&quot;, this.getStudentName);<br>    &#125;<br>  &#125;<br>&lt;/script&gt;<br><br>&lt;style scoped&gt;<br> .app&#123;<br>  background-color: gray;<br>  padding: 5px;<br> &#125;<br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>

<blockquote>
<p>总结：</p>
<ol>
<li><p>一种组件间通信的方式，适用于：<strong style="color:red">子组件 ===&gt; 父组件</strong></p>
</li>
<li><p>使用场景：A是父组件，B是子组件，B想给A传数据，那么就要在A中给B绑定自定义事件（<span style="color:red">事件的回调在A中</span>）。</p>
</li>
<li><p>绑定自定义事件：</p>
<ol>
<li><p>第一种方式，在父组件中：<code>&lt;Demo @atguigu=&quot;test&quot;/&gt;</code>  或 <code>&lt;Demo v-on:atguigu=&quot;test&quot;/&gt;</code></p>
</li>
<li><p>第二种方式，在父组件中：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs js">&lt;Demo ref=<span class="hljs-string">&quot;demo&quot;</span>/&gt;<br>......<br><span class="hljs-function"><span class="hljs-title">mounted</span>(<span class="hljs-params"></span>)</span>&#123;<br>   <span class="hljs-built_in">this</span>.$refs.xxx.$on(<span class="hljs-string">&#x27;atguigu&#x27;</span>,<span class="hljs-built_in">this</span>.test)<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li><p>若想让自定义事件只能触发一次，可以使用<code>once</code>修饰符，或<code>$once</code>方法。</p>
</li>
</ol>
</li>
<li><p>触发自定义事件：<code>this.$emit(&#39;atguigu&#39;,数据)</code>        </p>
</li>
<li><p>解绑自定义事件<code>this.$off(&#39;atguigu&#39;)</code></p>
</li>
<li><p>组件上也可以绑定原生DOM事件，需要使用<code>native</code>修饰符，如 <code>&lt;Student @click.native=&quot;show&quot;&gt;&lt;Student&gt;</code>，此时就可以添加 Studnet 组件触发 show 回调函数。</p>
</li>
<li><p>注意：通过<code>this.$refs.xxx.$on(&#39;atguigu&#39;,回调)</code>绑定自定义事件时，回调<span style="color:red">要么配置在methods中</span>，<span style="color:red">要么用箭头函数</span>，否则this指向会出问题！</p>
</li>
</ol>
</blockquote>
<h2 id="11-完善-TodoList（子组件向父组件传递值）"><a href="#11-完善-TodoList（子组件向父组件传递值）" class="headerlink" title="11.完善 TodoList（子组件向父组件传递值）"></a>11.完善 TodoList（子组件向父组件传递值）</h2><p>在 App.vue 中为子组件用上自定义组件</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;div id=&quot;root&quot;&gt;<br>    &lt;div class=&quot;todo-container&quot;&gt;<br>      &lt;div class=&quot;todo-wrap&quot;&gt;<br>        &lt;TodoHeader @askForTodoItem=&quot;askForTodoItem&quot;&gt;&lt;/TodoHeader&gt;<br>        &lt;TodoList :todoList=&quot;todoList&quot; :changeCheck=&quot;changeCheck&quot; :deleteTodoItem=&quot;deleteTodoItem&quot;&gt;&lt;/TodoList&gt;<br>        &lt;TodoFooter :todoList=&quot;todoList&quot; @selectAll=&quot;selectAll&quot; @clearCompletedEvent=&quot;clearCompletedEvent&quot;&gt;&lt;/TodoFooter&gt;<br>      &lt;/div&gt;<br>    &lt;/div&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br></code></pre></td></tr></table></figure>

<p>触发 <code>askForTodoItem</code> 事件，TodoHeader 组件就将新<strong>输入的事件对象</strong>作为参数传递给 App 组件</p>
<p>在 TodoHeader.vue 中，只要修改了第 7 行</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-function"><span class="hljs-title">addTodoItem</span>(<span class="hljs-params"></span>)</span> &#123;<br>    <span class="hljs-comment">// 校验输入的数据</span><br>    <span class="hljs-keyword">if</span>(!<span class="hljs-built_in">this</span>.eventName.trim()) <span class="hljs-keyword">return</span> alert(<span class="hljs-string">&quot;输入不能为空&quot;</span>);<br>    <span class="hljs-comment">// 将 eventName 封装成一个 todoItem</span><br>    <span class="hljs-keyword">const</span> todoItem = &#123;<span class="hljs-attr">id</span>: nanoid(), <span class="hljs-attr">eventName</span>: <span class="hljs-built_in">this</span>.eventName, <span class="hljs-attr">complete</span>: <span class="hljs-literal">false</span>&#125;;<br>    <span class="hljs-comment">// 触发事件，传递数据</span><br>    <span class="hljs-built_in">this</span>.$emit(<span class="hljs-string">&quot;askForTodoItem&quot;</span>, todoItem)<br>    <span class="hljs-comment">// 清空文本框输入</span><br>    <span class="hljs-built_in">this</span>.eventName = <span class="hljs-string">&quot;&quot;</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>触发 <code>selectAll</code> 事件，TodoFooter 组件就将<strong>全选框的状态值</strong>作为参数传递给 App 组件</p>
<p>在 TodoFooter.vue 中，只要修改了第 7 行</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">// 判断选中的和总数是否相同</span><br><span class="hljs-attr">isAll</span>: &#123;<br>  <span class="hljs-function"><span class="hljs-title">get</span>(<span class="hljs-params"></span>)</span> &#123;<br>    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.totalCount === <span class="hljs-built_in">this</span>.completedCount &amp;&amp; <span class="hljs-built_in">this</span>.totalCount &gt; <span class="hljs-number">0</span>;<br>  &#125;,<br>  <span class="hljs-function"><span class="hljs-title">set</span>(<span class="hljs-params">value</span>)</span> &#123;<br>    <span class="hljs-built_in">this</span>.$emit(<span class="hljs-string">&quot;selectAll&quot;</span>, value);<br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>触发 <code>clearCompletedEvent</code> 事件，之后 App 组件中 <code>clearCompletedEvent</code> 回到函数就会开始执行</p>
<p>在 TodoFooter.vue 中，只要修改了第 2 行</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-function"><span class="hljs-title">handleClearCompletedEvent</span>(<span class="hljs-params"></span>)</span> &#123;<br>  <span class="hljs-built_in">this</span>.$emit(<span class="hljs-string">&quot;clearCompletedEvent&quot;</span>);<br>&#125;<br></code></pre></td></tr></table></figure>



<h2 id="12-全局事件总线（GlobalEventBus）"><a href="#12-全局事件总线（GlobalEventBus）" class="headerlink" title="12.全局事件总线（GlobalEventBus）"></a>12.全局事件总线（GlobalEventBus）</h2><p>全局事件总线是用来解决组件之间的通信问题的。</p>
<p>使用全局事件总线可以实现任意两个组件之间的数据传递。</p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210806/image.118zwi9ztxj4.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<p>Vue 中并没有提供什么特殊的 API 来完成组件通讯，全局事件总线只是我们通过已有的知识，实现的一个功能。</p>
<p>全局事件总线本质就是一个对象，这个对象需要被所有组件都可以看到，并且可以使用 <code>$on</code> 绑定事件，<code>$emit</code> 触发事件，<code>$off</code> 解绑事件。</p>
<ol>
<li><strong>解决全局可见</strong>：由于一个重要的内置关系 <code>VueComponent.prototype.__proto__ === Vue.prototype</code>，所以我们就可以将对象放在 Vue 的原型对象上，这样所有组件实例对象都可以通过原型访问到这个对象。</li>
<li><strong>解决事件调用</strong>：<code>$on</code>、<code>$emit</code>、<code>$off</code> 这些方法都出现在 vm 和 vc 上，由于 vc 是组件实例对象，每一个组件都是一个组件实例对象，不唯一，所以 vm 是最后的选择。</li>
</ol>
<p>因此我们可以将 vm 对象放到 Vue 的原型对象中，作为全局事件总线。</p>
<p>因此在 main.js 中</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">new</span> Vue(&#123;<br>    <span class="hljs-attr">el</span>: <span class="hljs-string">&#x27;#app&#x27;</span>,<br>    <span class="hljs-attr">render</span>: <span class="hljs-function"><span class="hljs-params">h</span> =&gt;</span> h(App),<br>    <span class="hljs-comment">// 通过钩子函数，将当前 vm 放入 Vue 的原型对象上，作为全局事件组件</span><br>    <span class="hljs-function"><span class="hljs-title">beforeCreate</span>(<span class="hljs-params"></span>)</span> &#123;<br>        <span class="hljs-comment">// 安装全局事件总线，此时总行名就是 $bus</span><br>        Vue.prototype.$bus = <span class="hljs-built_in">this</span>;<br>    &#125;<br>&#125;)<br></code></pre></td></tr></table></figure>

<p>实现两个兄弟组件之间的通讯 Student.vue 向 School.vue 中传递数据</p>
<p>School.vue（重点在 26-35 行）中绑定和解绑事件</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;!-- 组件的结构 --&gt;<br>  &lt;div class=&quot;demo&quot;&gt;<br>    &lt;h2&gt;学校名称：&#123;&#123;name&#125;&#125;&lt;/h2&gt;<br>    &lt;h2&gt;学校地址：&#123;&#123;address&#125;&#125;&lt;/h2&gt;<br>    &lt;h2&gt;学生姓名：&#123;&#123;studentName&#125;&#125;&lt;/h2&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>// 组件的交互相关的代码<br>export default &#123;<br>  name: &quot;School&quot;,<br>  data() &#123;<br>    return &#123;<br>      name: &quot;尚硅谷&quot;,<br>      address: &quot;北京&quot;,<br>      studentName: &#x27;&#x27;<br>    &#125;<br>  &#125;,<br>  methods: &#123;<br>    getStudentName(studentName) &#123;<br>      this.studentName = studentName;<br>    &#125;<br>  &#125;,<br>  // 在组件挂载后绑定事件<br>  mounted() &#123;<br>    // 绑定事件<br>    this.$bus.$on(&quot;getStudentName&quot;, this.getStudentName);<br>  &#125;,<br>  // 在组件销毁前解绑当前组件绑定的事件<br>  beforeDestroy() &#123;<br>    // 解绑事件<br>    this.$bus.$off(&quot;getStudentName&quot;);<br>  &#125;<br>&#125;<br>&lt;/script&gt;<br><br>&lt;style scoped&gt;<br>  .demo &#123;<br>    background: orange;<br>  &#125;<br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>

<p>Student.vue（重点在 23 行）中触发事件</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;!-- 组件的结构 --&gt;<br>  &lt;div class=&quot;demo&quot;&gt;<br>    &lt;h2&gt;学生姓名：&#123;&#123;name&#125;&#125;&lt;/h2&gt;<br>    &lt;h2&gt;学生年龄：&#123;&#123;age&#125;&#125;&lt;/h2&gt;<br>    &lt;button @click=&quot;sendStudentName&quot;&gt;发送学生姓名到学校&lt;/button&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>// 组件的交互相关的代码<br>export default &#123;<br>  name: &quot;Student&quot;,<br>  data() &#123;<br>    return &#123;<br>      name: &quot;张三&quot;,<br>      age: 20<br>    &#125;<br>  &#125;,<br>  methods: &#123;<br>    sendStudentName() &#123;<br>      // 触发事件<br>      this.$bus.$emit(&quot;getStudentName&quot;, this.name);<br>    &#125;<br>  &#125;<br>&#125;<br>&lt;/script&gt;<br><br>&lt;style scoped&gt;<br>.demo &#123;<br>  background: pink;<br>&#125;<br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>

<p>App.vue</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;div class=&quot;demo&quot;&gt;<br>    &lt;School&gt;&lt;/School&gt;<br>    &lt;Student&gt;&lt;/Student&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>import Student from &quot;./components/Student&quot;;<br>import School from &quot;./components/School&quot;;<br><br>export default &#123;<br>  name: &quot;App&quot;,<br>  components: &#123;Student, School&#125;,<br>&#125;<br>&lt;/script&gt;<br><br>&lt;style&gt;<br>  .demo &#123;<br>    background: gray;<br>  &#125;<br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>

<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210806/image.19xpvsutlcgw.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<blockquote>
<p>总结：</p>
<ol>
<li><p>一种组件间通信的方式，适用于<span style="color:red">任意组件间通信</span>。</p>
</li>
<li><p>安装全局事件总线：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">new</span> Vue(&#123;<br>	......<br>	<span class="hljs-function"><span class="hljs-title">beforeCreate</span>(<span class="hljs-params"></span>)</span> &#123;<br>		Vue.prototype.$bus = <span class="hljs-built_in">this</span> <span class="hljs-comment">//安装全局事件总线，$bus就是当前应用的vm</span><br>	&#125;,<br>    ......<br>&#125;) <br></code></pre></td></tr></table></figure></li>
<li><p>使用事件总线：</p>
<ol>
<li><p>接收数据：A组件想接收数据，则在A组件中给$bus绑定自定义事件，事件的<span style="color:red">回调留在A组件自身。</span></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-function"><span class="hljs-title">methods</span>(<span class="hljs-params"></span>)</span>&#123;<br>  <span class="hljs-function"><span class="hljs-title">demo</span>(<span class="hljs-params">data</span>)</span>&#123;......&#125;<br>&#125;<br>......<br><span class="hljs-function"><span class="hljs-title">mounted</span>(<span class="hljs-params"></span>)</span> &#123;<br>  <span class="hljs-built_in">this</span>.$bus.$on(<span class="hljs-string">&#x27;xxxx&#x27;</span>,<span class="hljs-built_in">this</span>.demo)<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li><p>提供数据：<code>this.$bus.$emit(&#39;xxxx&#39;,数据)</code></p>
</li>
</ol>
</li>
<li><p>最好在beforeDestroy钩子中，用$off去解绑<span style="color:red">当前组件所用到的</span>事件。</p>
</li>
</ol>
</blockquote>
<h2 id="13-在-TodoList-中使用全局事件总线"><a href="#13-在-TodoList-中使用全局事件总线" class="headerlink" title="13.在 TodoList 中使用全局事件总线"></a>13.在 TodoList 中使用全局事件总线</h2><p>使用全局事件总线来实现 <code>App</code> 组件和 <code>TodoItem</code> 组件之间的数据传递</p>
<p>此时数据传递已经不需要 <code>TodoList</code> 组件了，因此可以在 <code>App</code> 组件中改写，值传递一个 todoList 数据，其他不用做了</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;TodoList :todoList=&quot;todoList&quot;&gt;&lt;/TodoList&gt;<br></code></pre></td></tr></table></figure>

<p>首先要在 main.js 中安装全局事件总线</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">new</span> Vue(&#123;<br>    <span class="hljs-attr">el</span>: <span class="hljs-string">&#x27;#app&#x27;</span>,<br>    <span class="hljs-attr">render</span>: <span class="hljs-function"><span class="hljs-params">h</span> =&gt;</span> h(App),<br>    <span class="hljs-comment">// 安装全局事件总线</span><br>    <span class="hljs-function"><span class="hljs-title">beforeCreate</span>(<span class="hljs-params"></span>)</span> &#123;<br>        Vue.prototype.$bus = <span class="hljs-built_in">this</span>;<br>    &#125;<br>&#125;)<br></code></pre></td></tr></table></figure>

<p>在 App.vue 中绑定和解绑事件</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-function"><span class="hljs-title">mounted</span>(<span class="hljs-params"></span>)</span> &#123;<br>  <span class="hljs-comment">// 绑定事件</span><br>  <span class="hljs-built_in">this</span>.$bus.$on(<span class="hljs-string">&quot;changeCheck&quot;</span>, <span class="hljs-built_in">this</span>.changeCheck);<br>  <span class="hljs-built_in">this</span>.$bus.$on(<span class="hljs-string">&quot;deleteTodoItem&quot;</span>, <span class="hljs-built_in">this</span>.deleteTodoItem);<br>&#125;,<br><span class="hljs-function"><span class="hljs-title">beforeDestroy</span>(<span class="hljs-params"></span>)</span> &#123;<br>  <span class="hljs-comment">// 解绑事件</span><br>  <span class="hljs-built_in">this</span>.$bus.$off(<span class="hljs-string">&quot;changeCheck&quot;</span>);<br>  <span class="hljs-built_in">this</span>.$bus.$off(<span class="hljs-string">&quot;deleteTodoItem&quot;</span>);<br>&#125;<br></code></pre></td></tr></table></figure>

<p>在 TodoItem.vue 总触发事件</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs js">methods: &#123;<br>  <span class="hljs-function"><span class="hljs-title">handleChangeCheck</span>(<span class="hljs-params">id</span>)</span> &#123;<br>    <span class="hljs-comment">// 触发事件</span><br>    <span class="hljs-built_in">this</span>.$bus.$emit(<span class="hljs-string">&quot;changeCheck&quot;</span>, id);<br>  &#125;,<br>  <span class="hljs-function"><span class="hljs-title">handleDeleteTodoItem</span>(<span class="hljs-params">id</span>)</span> &#123;<br>    <span class="hljs-comment">// 触发事件</span><br>    <span class="hljs-built_in">this</span>.$bus.$emit(<span class="hljs-string">&quot;deleteTodoItem&quot;</span>, id);<br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure>



<h2 id="14-消息订阅与发布"><a href="#14-消息订阅与发布" class="headerlink" title="14.消息订阅与发布"></a>14.消息订阅与发布</h2><ol>
<li><p>一种组件间通信的方式，适用于<span style="color:red">任意组件间通信</span>。</p>
</li>
<li><p>使用步骤：</p>
<ol>
<li><p>安装 pubsub：<code>npm i pubsub-js</code></p>
</li>
<li><p>引入: <code>import pubsub from &#39;pubsub-js&#39;</code></p>
</li>
<li><p>接收数据：A 组件想接收数据，则在A组件中订阅消息，订阅的<span style="color:red">回调留在A组件自身。</span></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-function"><span class="hljs-title">methods</span>(<span class="hljs-params"></span>)</span>&#123;<br>  <span class="hljs-function"><span class="hljs-title">demo</span>(<span class="hljs-params">eventName, data</span>)</span>&#123;......&#125;<br>&#125;<br>......<br><span class="hljs-function"><span class="hljs-title">mounted</span>(<span class="hljs-params"></span>)</span> &#123;<br>  <span class="hljs-built_in">this</span>.pid = pubsub.subscribe(<span class="hljs-string">&#x27;xxx&#x27;</span>,<span class="hljs-built_in">this</span>.demo) <span class="hljs-comment">//订阅消息</span><br>&#125;<br></code></pre></td></tr></table></figure></li>
<li><p>提供数据：<code>pubsub.publish(&#39;xxx&#39;,数据)</code></p>
</li>
<li><p>最好在beforeDestroy钩子中，用<code>PubSub.unsubscribe(pid)</code>去<span style="color:red">取消订阅。</span></p>
</li>
<li><p>注意一个点：订阅消息是的回调函数收到的<strong>第一个数据是事件名称，第二个数据才是发布者传递过来的数据</strong></p>
</li>
</ol>
</li>
</ol>
<h2 id="15-为-TodoList-添加一个修改数据的操作"><a href="#15-为-TodoList-添加一个修改数据的操作" class="headerlink" title="15.为 TodoList 添加一个修改数据的操作"></a>15.为 TodoList 添加一个修改数据的操作</h2><h3 id="15-1-在-TodoItem-中添加一个修改按钮"><a href="#15-1-在-TodoItem-中添加一个修改按钮" class="headerlink" title="15.1 在 TodoItem 中添加一个修改按钮"></a>15.1 在 TodoItem 中添加一个修改按钮</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;btn btn-edit&quot;</span>&gt;</span>修改<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br></code></pre></td></tr></table></figure>

<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs css"><span class="hljs-selector-class">.btn-edit</span> &#123;<br>  <span class="hljs-attribute">color</span>: <span class="hljs-number">#fff</span>;<br>  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#268aee</span>;<br>  <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#265cec</span>;<br>  <span class="hljs-attribute">margin-right</span>: <span class="hljs-number">5px</span>;<br>&#125;<br><br><span class="hljs-selector-class">.btn-edit</span><span class="hljs-selector-pseudo">:hover</span> &#123;<br>  <span class="hljs-attribute">color</span>: <span class="hljs-number">#fff</span>;<br>  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#265cec</span>;<br>&#125;<br></code></pre></td></tr></table></figure>



<h3 id="15-2-为修改按钮添加方法"><a href="#15-2-为修改按钮添加方法" class="headerlink" title="15.2 为修改按钮添加方法"></a>15.2 为修改按钮添加方法</h3><p>按下修改按钮将 span 标签改为可修改的 input 标签</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;checkbox&quot;</span> <span class="hljs-attr">:checked</span>=<span class="hljs-string">&quot;todoItem.complete&quot;</span> @<span class="hljs-attr">change</span>=<span class="hljs-string">&quot;handleChangeCheck(todoItem.id)&quot;</span>/&gt;</span><br>    <span class="hljs-comment">&lt;!-- 通过 todoItem.isEdit 的值决定要显示哪个 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">v-show</span>=<span class="hljs-string">&quot;!todoItem.isEdit&quot;</span>&gt;</span>&#123;&#123;eventName&#125;&#125;<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">v-show</span>=<span class="hljs-string">&quot;todoItem.isEdit&quot;</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;text&quot;</span> <span class="hljs-attr">v-model</span>=<span class="hljs-string">&quot;eventName&quot;</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;btn btn-danger&quot;</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">&quot;handleDeleteTodoItem(todoItem.id)&quot;</span>&gt;</span>删除<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br>  <span class="hljs-comment">&lt;!-- 按下按钮修改 todoItem.isEdit 的值为 true --&gt;</span>  <br>  <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;btn btn-edit&quot;</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">&quot;handleEditTodoItem(todoItem)&quot;</span>&gt;</span>修改<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span><br></code></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-function"><span class="hljs-title">data</span>(<span class="hljs-params"></span>)</span> &#123;<br>  <span class="hljs-keyword">return</span> &#123;<br>    <span class="hljs-attr">eventName</span>: <span class="hljs-built_in">this</span>.todoItem.eventName,<br>  &#125;<br>&#125;,<br><span class="hljs-attr">methods</span>: &#123;<br>    <span class="hljs-function"><span class="hljs-title">handleEditTodoItem</span>(<span class="hljs-params">todoItem</span>)</span> &#123;<br>        <span class="hljs-comment">// 为 todoItem 添加一个属性 isEdit，表示是否修改过</span><br>        <span class="hljs-keyword">if</span>(todoItem.hasOwnProperty(<span class="hljs-string">&#x27;isEdit&#x27;</span>)) &#123;<br>            <span class="hljs-comment">// 如果已经存在了这个属性，就将值赋为 true</span><br>            todoItem.isEdit = <span class="hljs-literal">true</span>;<br>        &#125; <span class="hljs-keyword">else</span> &#123;<br>            <span class="hljs-comment">// 如果不存在，就为 todoItem 添加这个属性</span><br>            <span class="hljs-built_in">this</span>.$set(todoItem, <span class="hljs-string">&#x27;isEdit&#x27;</span>, <span class="hljs-literal">true</span>);<br>        &#125;<br>    &#125;<br>&#125;    <br></code></pre></td></tr></table></figure>

<p>当 input 标签失去焦点或按下 enter 键后，更新数据，重新展示 span 标签</p>
<p>在 input 中添加两个事件</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">v-show</span>=<span class="hljs-string">&quot;todoItem.isEdit&quot;</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;text&quot;</span> <span class="hljs-attr">v-model</span>=<span class="hljs-string">&quot;eventName&quot;</span> @<span class="hljs-attr">blur</span>=<span class="hljs-string">&quot;updateEventName(todoItem)&quot;</span> @<span class="hljs-attr">keyup.enter</span>=<span class="hljs-string">&quot;updateEventName(todoItem)&quot;</span>&gt;</span><br></code></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-function"><span class="hljs-title">updateEventName</span>(<span class="hljs-params">todoItem</span>)</span> &#123;<br>  todoItem.isEdit = <span class="hljs-literal">false</span>;<br>  <span class="hljs-comment">// 使用全局事件总线，触发事件</span><br>  <span class="hljs-built_in">this</span>.$bus.$emit(<span class="hljs-string">&#x27;updateEventName&#x27;</span>, todoItem.id, <span class="hljs-built_in">this</span>.eventName);<br>&#125;<br></code></pre></td></tr></table></figure>

<p>在 App.vue 中绑定事件</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-function"><span class="hljs-title">mounted</span>(<span class="hljs-params"></span>)</span> &#123;<br>  <span class="hljs-comment">// 绑定事件</span><br>  <span class="hljs-built_in">this</span>.$bus.$on(<span class="hljs-string">&quot;updateEventName&quot;</span>, <span class="hljs-built_in">this</span>.updateEventName);<br>&#125;,<br><span class="hljs-function"><span class="hljs-title">beforeDestroy</span>(<span class="hljs-params"></span>)</span> &#123;<br>  <span class="hljs-comment">// 解绑事件</span><br>  <span class="hljs-built_in">this</span>.$bus.$off(<span class="hljs-string">&quot;updateEventName&quot;</span>);<br>&#125;<br></code></pre></td></tr></table></figure>

<p>回调函数 updateEventName</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * 修改事件名称</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@param <span class="hljs-variable">id</span></span></span><br><span class="hljs-comment"> * <span class="hljs-doctag">@param <span class="hljs-variable">eventName</span></span></span><br><span class="hljs-comment"> */</span><br><span class="hljs-function"><span class="hljs-title">updateEventName</span>(<span class="hljs-params">id, eventName</span>)</span> &#123;<br>  <span class="hljs-built_in">this</span>.todoList.forEach(<span class="hljs-function">(<span class="hljs-params">todoItem</span>) =&gt;</span> &#123;<br>    <span class="hljs-keyword">if</span> (todoItem.id === id) &#123;<br>      todoItem.eventName = eventName;<br>    &#125;<br>  &#125;)<br>&#125;<br></code></pre></td></tr></table></figure>



<h3 id="15-3-input-框自动获取焦点"><a href="#15-3-input-框自动获取焦点" class="headerlink" title="15.3 input 框自动获取焦点"></a>15.3 input 框自动获取焦点</h3><p>在 input 中添加一个 ref 属性</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">v-show</span>=<span class="hljs-string">&quot;todoItem.isEdit&quot;</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;text&quot;</span> <span class="hljs-attr">v-model</span>=<span class="hljs-string">&quot;eventName&quot;</span> @<span class="hljs-attr">blur</span>=<span class="hljs-string">&quot;updateEventName(todoItem)&quot;</span> @<span class="hljs-attr">keyup.enter</span>=<span class="hljs-string">&quot;updateEventName(todoItem)&quot;</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">&quot;editInput&quot;</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>在 handleEditTodoItem 中添加操作</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-function"><span class="hljs-title">handleEditTodoItem</span>(<span class="hljs-params">todoItem</span>)</span> &#123;<br>  <span class="hljs-comment">// 为 todoItem 添加一个属性 isEdit，表示是否修改过</span><br>  <span class="hljs-keyword">if</span>(todoItem.hasOwnProperty(<span class="hljs-string">&#x27;isEdit&#x27;</span>)) &#123;<br>    <span class="hljs-comment">// 如果已经存在了这个属性，就将值赋为 true</span><br>    todoItem.isEdit = <span class="hljs-literal">true</span>;<br>  &#125; <span class="hljs-keyword">else</span> &#123;<br>    <span class="hljs-comment">// 如果不存在，就为 todoItem 添加这个属性</span><br>    <span class="hljs-built_in">this</span>.$set(todoItem, <span class="hljs-string">&#x27;isEdit&#x27;</span>, <span class="hljs-literal">true</span>);<br>  &#125;<br>  <span class="hljs-comment">// 自动获取焦点</span><br>  <span class="hljs-built_in">this</span>.$nextTick(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>&#123;<br>    <span class="hljs-built_in">this</span>.$refs.editInput.focus();<br>  &#125;)<br>&#125;<br></code></pre></td></tr></table></figure>

<blockquote>
<p><strong>nextTick</strong></p>
<ol>
<li>语法：<code>this.$nextTick(回调函数)</code></li>
<li>作用：在下一次 DOM 更新结束后执行其指定的回调。</li>
<li>什么时候用：当改变数据后，要基于更新后的新 DOM 进行某些操作时，要在 nextTick 所指定的回调函数中执行。</li>
</ol>
</blockquote>
<h2 id="16-Vue-封装的过渡与动画"><a href="#16-Vue-封装的过渡与动画" class="headerlink" title="16.Vue 封装的过渡与动画"></a>16.Vue 封装的过渡与动画</h2><ol>
<li><p>作用：在插入、更新或移除 DOM元素时，在合适的时候给元素添加样式类名。</p>
</li>
<li><p>图示：<img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210806/transition.2n7g6mf6gte0.png" srcset="/img/loading.gif" lazyload alt="transition"></p>
</li>
<li><p>写法：</p>
<ol>
<li><p>准备好样式：</p>
<ul>
<li>元素进入的样式：<ol>
<li>v-enter：进入的起点</li>
<li>v-enter-active：进入过程中</li>
<li>v-enter-to：进入的终点</li>
</ol>
</li>
<li>元素离开的样式：<ol>
<li>v-leave：离开的起点</li>
<li>v-leave-active：离开过程中</li>
<li>v-leave-to：离开的终点</li>
</ol>
</li>
</ul>
</li>
<li><p>使用<code>&lt;transition&gt;</code>包裹要过度的元素，并配置 name 属性：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;transition name=&quot;hello&quot;&gt;<br>	&lt;h1 v-show=&quot;isShow&quot;&gt;你好啊！&lt;/h1&gt;<br>&lt;/transition&gt;<br></code></pre></td></tr></table></figure></li>
<li><p>备注：若有多个元素需要过度，则需要使用：<code>&lt;transition-group&gt;</code>，且每个元素都要指定<code>key</code>值。</p>
</li>
</ol>
</li>
</ol>
<p><a target="_blank" rel="noopener" href="https://cn.vuejs.org/v2/guide/transitions.html">参考官网</a></p>
<h3 id="16-1-使用动画"><a href="#16-1-使用动画" class="headerlink" title="16.1 使用动画"></a>16.1 使用动画</h3><p>Student.vue</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;div&gt;<br>    &lt;button @click=&quot;isShow = !isShow&quot;&gt;插入 / 移除&lt;/button&gt;<br>    &lt;transition appear&gt;<br>        &lt;h1 v-show=&quot;isShow&quot;&gt;Vue 封装的动画&lt;/h1&gt;<br>    &lt;/transition&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>export default &#123;<br>    name: &#x27;Student&#x27;,<br>    data() &#123; <br>        return &#123;<br>            isShow: true,<br>        &#125;<br>    &#125;<br>&#125;<br>&lt;/script&gt;<br><br>&lt;style scoped&gt;<br>	h1&#123;<br>		background-color: orange;<br>	&#125;<br><br>	.v-enter-active&#123;<br>		animation: yechen 0.5s linear;<br>	&#125;<br><br>	.v-leave-active&#123;<br>		animation: yechen 0.5s linear reverse;<br>	&#125;<br><br>	@keyframes yechen &#123;<br>		from&#123;<br>			transform: translateX(-100%);<br>		&#125;<br>		to&#123;<br>			transform: translateX(0px);<br>		&#125;<br>	&#125;<br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>



<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210806/QQ%E5%BD%95%E5%B1%8F20210806204455.4g9eyzz5ydu0.gif" srcset="/img/loading.gif" lazyload alt="QQ录屏20210806204455"></p>
<h3 id="16-2-使用过渡"><a href="#16-2-使用过渡" class="headerlink" title="16.2 使用过渡"></a>16.2 使用过渡</h3><p>Student1.vue</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;div&gt;<br>    &lt;button @click=&quot;isShow = !isShow&quot;&gt;插入 / 移除&lt;/button&gt;<br>    &lt;transition name=&quot;hello&quot; appear&gt;<br>        &lt;h1 v-show=&quot;isShow&quot;&gt;Vue 封装的过渡&lt;/h1&gt;<br>    &lt;/transition&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>export default &#123;<br>    name: &#x27;Student&#x27;,<br>    data() &#123; <br>        return &#123;<br>            isShow: true,<br>        &#125;<br>    &#125;<br>&#125;<br>&lt;/script&gt;<br><br>&lt;style scoped&gt;<br>	h1&#123;<br>		background-color: orange;<br>	&#125;<br>	/* 进入的起点、离开的终点 */<br>	.hello-enter,.hello-leave-to&#123;<br>		transform: translateX(-100%);<br>	&#125;<br>	.hello-enter-active,.hello-leave-active&#123;<br>		transition: 0.5s linear;<br>	&#125;<br>	/* 进入的终点、离开的起点 */<br>	.hello-enter-to,.hello-leave&#123;<br>		transform: translateX(0);<br>	&#125;<br><br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>

<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210806/QQ%E5%BD%95%E5%B1%8F20210806205439.13md5tb2ceu8.gif" srcset="/img/loading.gif" lazyload alt="QQ录屏20210806205439"></p>
<h3 id="16-3-使用-css-库产生炫酷样式"><a href="#16-3-使用-css-库产生炫酷样式" class="headerlink" title="16.3 使用 css 库产生炫酷样式"></a>16.3 使用 css 库产生炫酷样式</h3><p>使用 <a target="_blank" rel="noopener" href="https://animate.style/">Animate.css</a> 提供的样式</p>
<p>Student3.vue</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;div&gt;<br>    &lt;button @click=&quot;isShow = !isShow&quot;&gt;插入 / 移除&lt;/button&gt;<br>    &lt;transition <br>		name=&quot;animate__animated animate__bounce&quot; <br>		appear<br>		enter-active-class=&quot;animate__heartBeat&quot;<br>		leave-active-class=&quot;animate__bounceOut&quot;<br>		&gt;<br>        &lt;h1 v-show=&quot;isShow&quot;&gt;使用 CSS 库&lt;/h1&gt;<br>    &lt;/transition&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>import &#x27;animate.css&#x27;<br>export default &#123;<br>    name: &#x27;Student&#x27;,<br>    data() &#123; <br>        return &#123;<br>            isShow: true,<br>        &#125;<br>    &#125;<br>&#125;<br>&lt;/script&gt;<br><br>&lt;style scoped&gt;<br>	h1&#123;<br>		color: orange;<br>	&#125;<br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>

<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210806/QQ%E5%BD%95%E5%B1%8F20210806210632.616g9k7fw7w0.gif" srcset="/img/loading.gif" lazyload alt="QQ录屏20210806210632"></p>
<h2 id="17-为-TodoList-添加动画效果"><a href="#17-为-TodoList-添加动画效果" class="headerlink" title="17.为 TodoList 添加动画效果"></a>17.为 TodoList 添加动画效果</h2><p>在事件添加和删除操作时，每一个 todoItem 的移入和移出都添加动画。</p>
<p>使用 <a target="_blank" rel="noopener" href="https://animate.style/">Animate.css</a> 提供的样式.</p>
<p>在 TodoItem 组件中添加 <code>&lt;transition&gt;</code> 标签，使用动画。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;transition appear<br>    name=&quot;animate__animated animate__bounce&quot;<br>    enter-active-class=&quot;animate__bounceInRight&quot;<br>    leave-active-class=&quot;animate__bounceOutLeft&quot;<br>    &gt;<br>    <br>    &lt;li&gt;<br>      ...<br>  &lt;/li&gt;<br>  &lt;/transition&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>import &#x27;animate.css&#x27;;<br>export default &#123;<br>  ...<br>&#125;<br>&lt;/script&gt;<br><br></code></pre></td></tr></table></figure>

<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210806/QQ%E5%BD%95%E5%B1%8F20210806212127.4g75fzfpn2u0.gif" srcset="/img/loading.gif" lazyload alt="QQ录屏20210806212127"></p>
<h2 id="18-Vue-中使用-ajax"><a href="#18-Vue-中使用-ajax" class="headerlink" title="18.Vue 中使用 ajax"></a>18.Vue 中使用 ajax</h2><p> Vue 推荐使用 <code>axios</code> 发送 ajax 请求</p>
<p>使用 <code>npm i axios</code> 命令安装 axios</p>
<p>提前使用 node.js 写好一个服务器，地址为 <a target="_blank" rel="noopener" href="http://localhost:5000/students%EF%BC%8C%E5%85%B6%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%E6%98%AF">http://localhost:5000/students，其中的数据是</a></p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210806/image.74y49i2ntbk0.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;button @click=&quot;requestStudents&quot;&gt;按我获取 Studnets&lt;/button&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>// 引入<br>import axios from &#x27;axios&#x27;;<br>export default &#123;<br>    name: &#x27;Student&#x27;,<br>    methods: &#123;<br>        requestStudents() &#123;<br>            // 发送请求<br>            axios.get(&#x27;http://localhost:5000/students&#x27;).then(<br>                response =&gt; &#123;<br>                    console.log(&quot;请求成功了&quot;, response.data);<br>                &#125;,<br>                error =&gt; &#123;<br>                    console.log(&quot;请求失败l&quot;, error.message);<br>                &#125;<br>            )<br>        &#125;<br>    &#125;<br>&#125;<br>&lt;/script&gt;<br></code></pre></td></tr></table></figure>

<p>按下按钮发送请求</p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210806/image.3vrx4yzk4420.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<p>出现了错误，错误原因是我们当前地址为 <a href="http://localhost:8080，但是我们访问的地址是">http://localhost:8080，但是我们访问的地址是</a> <a target="_blank" rel="noopener" href="http://localhost:5000/studnets%EF%BC%8C%E8%BF%99%E6%98%AF%E4%B8%80%E4%B8%AA%E8%B7%A8%E5%9F%9F%E8%AF%B7%E6%B1%82%EF%BC%8C%E7%94%B1%E4%BA%8E%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%AB%AF%E6%B2%A1%E6%9C%89%E9%85%8D%E7%BD%AE%E5%93%8D%E5%BA%94%E5%A4%B4%EF%BC%8C%E6%89%80%E4%BB%A5%E6%B5%8F%E8%A7%88%E5%99%A8%E6%B2%A1%E6%9C%89%E5%B0%86%E8%8E%B7%E5%8F%96%E5%88%B0%E7%9A%84%E6%95%B0%E6%8D%AE%E5%8F%8D%E4%BC%9A%E7%BB%99%E6%88%91%E4%BB%AC%E3%80%82">http://localhost:5000/studnets，这是一个跨域请求，由于服务器端没有配置响应头，所以浏览器没有将获取到的数据反会给我们。</a></p>
<p><strong>解决跨域的办法：</strong></p>
<p>使用 Vue 给我们提供的一个代理服务器，这个服务器地址和我们的访问地址是一样的，因此不存在跨域请求，同时，两个服务器之间是通过 http 协议交流的，不存在跨域问题，这样问题就解决了。</p>
<h3 id="方法一"><a href="#方法一" class="headerlink" title="方法一"></a>方法一</h3><p>​    在 vue.config.js 中添加如下配置：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs js">devServer:&#123;<br>  <span class="hljs-attr">proxy</span>:<span class="hljs-string">&quot;http://localhost:5000&quot;</span><br>&#125;<br></code></pre></td></tr></table></figure>

<p>说明：</p>
<ol>
<li>优点：配置简单，请求资源时直接发给前端（8080）即可。</li>
<li>缺点：不能配置多个代理，不能灵活的控制请求是否走代理。</li>
<li>工作方式：若按照上述配置代理，当请求了前端不存在的资源时，那么该请求会转发给服务器 （优先匹配前端资源）</li>
</ol>
<h3 id="方法二"><a href="#方法二" class="headerlink" title="方法二"></a>方法二</h3><p>​    编写 vue.config.js 配置具体代理规则：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-built_in">module</span>.exports = &#123;<br>	<span class="hljs-attr">devServer</span>: &#123;<br>      <span class="hljs-attr">proxy</span>: &#123;<br>      <span class="hljs-string">&#x27;/api1&#x27;</span>: &#123;<span class="hljs-comment">// 匹配所有以 &#x27;/api1&#x27;开头的请求路径</span><br>        <span class="hljs-attr">target</span>: <span class="hljs-string">&#x27;http://localhost:5000&#x27;</span>,<span class="hljs-comment">// 代理目标的基础路径</span><br>        <span class="hljs-attr">changeOrigin</span>: <span class="hljs-literal">true</span>,<br>        <span class="hljs-attr">pathRewrite</span>: &#123;<span class="hljs-string">&#x27;^/api1&#x27;</span>: <span class="hljs-string">&#x27;&#x27;</span>&#125;<span class="hljs-comment">// 将所有 /api1 开头的路径替换成 &#x27;&#x27;,保证到服务中获取资源时路径正确</span><br>      &#125;,<br>      <span class="hljs-string">&#x27;/api2&#x27;</span>: &#123;<span class="hljs-comment">// 匹配所有以 &#x27;/api2&#x27;开头的请求路径</span><br>        <span class="hljs-attr">target</span>: <span class="hljs-string">&#x27;http://localhost:5001&#x27;</span>,<span class="hljs-comment">// 代理目标的基础路径</span><br>        <span class="hljs-attr">changeOrigin</span>: <span class="hljs-literal">true</span>,<br>        <span class="hljs-attr">pathRewrite</span>: &#123;<span class="hljs-string">&#x27;^/api2&#x27;</span>: <span class="hljs-string">&#x27;&#x27;</span>&#125;<br>      &#125;<br>    &#125;<br>  &#125;<br>&#125;<br><span class="hljs-comment">/*</span><br><span class="hljs-comment">   changeOrigin 设置为 true 时，服务器收到的请求头中的 host 为：localhost:5000</span><br><span class="hljs-comment">   changeOrigin 设置为 false 时，服务器收到的请求头中的 host 为：localhost:8080</span><br><span class="hljs-comment">   changeOrigin 默认值为 true</span><br><span class="hljs-comment">*/</span><br></code></pre></td></tr></table></figure>

<p>说明：</p>
<ol>
<li>优点：可以配置多个代理，且可以灵活的控制请求是否走代理。</li>
<li>缺点：配置略微繁琐，请求资源时必须加前缀。</li>
</ol>
<p>Student.vue</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;button @click=&quot;requestStudents&quot;&gt;按我获取 Studnets&lt;/button&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>import axios from &#x27;axios&#x27;;<br>export default &#123;<br>    name: &#x27;Student&#x27;,<br>    methods: &#123;<br>        requestStudents() &#123;<br>            axios.get(&#x27;http://localhost:8080/yechen/students&#x27;).then(<br>                response =&gt; &#123;<br>                    console.log(&quot;请求成功了&quot;, response.data);<br>                &#125;,<br>                error =&gt; &#123;<br>                    console.log(&quot;请求失败l&quot;, error.message);<br>                &#125;<br>            )<br>        &#125;<br>    &#125;<br>&#125;<br>&lt;/script&gt;<br><br></code></pre></td></tr></table></figure>

<p>vue.config.js</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-built_in">module</span>.exports = &#123;<br>    <span class="hljs-attr">devServer</span>: &#123;<br>      <span class="hljs-attr">proxy</span>: &#123;<br>        <span class="hljs-string">&#x27;/yechen&#x27;</span>: &#123;<br>          <span class="hljs-attr">target</span>: <span class="hljs-string">&#x27;http://localhost:5000&#x27;</span>,<br>          <span class="hljs-attr">pathRewrite</span>: &#123;<span class="hljs-string">&#x27;^/yechen&#x27;</span>:<span class="hljs-string">&#x27;&#x27;</span>&#125;,<br>          <span class="hljs-attr">ws</span>: <span class="hljs-literal">true</span>,<br>          <span class="hljs-attr">changeOrigin</span>: <span class="hljs-literal">true</span>,<br>        &#125;<br>      &#125;<br>    &#125;,<br>    <span class="hljs-comment">// 关闭语法检查</span><br>    <span class="hljs-attr">lintOnSave</span>: <span class="hljs-literal">false</span><br>&#125;<br></code></pre></td></tr></table></figure>

<p>测试</p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210806/image.29q0sj2yd5a8.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<h2 id="19-通过github提供的api接口搜索用户"><a href="#19-通过github提供的api接口搜索用户" class="headerlink" title="19.通过github提供的api接口搜索用户"></a>19.通过github提供的api接口搜索用户</h2><p>github 提供了一个 api 接口可以获取用户信息 <a target="_blank" rel="noopener" href="https://api.github.com/search/users?q=keyword">https://api.github.com/search/users?q=keyword</a></p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210807/QQ%E5%BD%95%E5%B1%8F20210807104522.24uk4o4c0ucg.gif" srcset="/img/loading.gif" lazyload alt="QQ录屏20210807104522"></p>
<p><a target="_blank" rel="noopener" href="https://www.bilibili.com/video/BV1Zy4y1K7SH?p=98">视频讲解</a></p>
<p>Search.vue</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;section class=&quot;jumbotron&quot;&gt;<br>    &lt;h3 class=&quot;jumbotron-heading&quot;&gt;Search Github Users&lt;/h3&gt;<br>    &lt;div&gt;<br>      &lt;input type=&quot;text&quot; placeholder=&quot;enter the name you search&quot; v-model=&quot;keyword&quot; @keyup.enter=&quot;searchGithub&quot;/&gt;&amp;nbsp;<br>      &lt;button @click=&quot;searchGithub&quot;&gt;Search&lt;/button&gt;<br>    &lt;/div&gt;<br>  &lt;/section&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>import axios from &quot;axios&quot;;<br><br>export default &#123;<br>  name: &quot;Search&quot;,<br>  data() &#123;<br>    return &#123;<br>      keyword: &#x27;&#x27;<br>    &#125;<br>  &#125;,<br>  methods: &#123;<br>    searchGithub() &#123;<br>      // 按下按钮，显示正在加载中<br>      this.$bus.$emit(&quot;userListData&quot;, &#123;<br>        userList: [],<br>        isFirst: false,<br>        isLoading: true,<br>        errMsg:&#x27;&#x27;<br>      &#125;);<br>      axios.get(`https://api.github.com/search/users?q=$&#123;this.keyword&#125;`).then(<br>        response =&gt; &#123;<br>          console.log(&quot;请求成功&quot;);<br>          // 请求成功，显示用户列表<br>          this.$bus.$emit(&quot;userListData&quot;, &#123;<br>            userList: response.data.items,<br>            isFirst: false,<br>            isLoading: false,<br>            errMsg:&#x27;&#x27;<br>          &#125;);<br>        &#125;,<br>        error =&gt; &#123;<br>          console.log(&quot;请求失败&quot;)<br>          // 请求失败，显示错误信息<br>          this.$bus.$emit(&quot;userListData&quot;, &#123;<br>            userList: [],<br>            isFirst: false,<br>            isLoading: false,<br>            errMsg:error.message<br>          &#125;);<br>        &#125;<br>      )<br><br>    &#125;<br>  &#125;<br>&#125;<br>&lt;/script&gt;<br><br>&lt;style scoped&gt;<br><br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>

<p>UserList.vue</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>    &lt;div class=&quot;row&quot;&gt;<br>      &lt;!-- 显示用户列表 --&gt;<br>      &lt;div v-show=&quot;userListData.userList.length&quot; class=&quot;card&quot; v-for=&quot;userItem in userListData.userList&quot; :key=&quot;userItem.login&quot;&gt;<br>        &lt;a :href=&quot;userItem.html_url&quot; target=&quot;_blank&quot;&gt;<br>          &lt;img :src=&quot;userItem.avatar_url&quot; style=&#x27;width: 100px&#x27;/&gt;<br>        &lt;/a&gt;<br>        &lt;p class=&quot;card-text&quot;&gt;&#123;&#123;userItem.login&#125;&#125;&lt;/p&gt;<br>      &lt;/div&gt;<br>      &lt;!-- 显示欢迎 --&gt;<br>      &lt;h1 v-show=&quot;userListData.isFirst&quot;&gt;Welcome to use！&lt;/h1&gt;<br>      &lt;!-- 显示加载中 --&gt;<br>      &lt;h1 v-show=&quot;userListData.isLoading&quot;&gt;Loading...&lt;/h1&gt;<br>      &lt;!-- 显示错误信息 --&gt;<br>      &lt;h1 v-show=&quot;userListData.errMsg&quot;&gt;&#123;&#123;userListData.errMsg&#125;&#125;&lt;/h1&gt;<br>    &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>export default &#123;<br>  name: &quot;UserList&quot;,<br>  data() &#123;<br>    return &#123;<br>      userListData: &#123;<br>        userList: [],<br>        isFirst: true,<br>        isLoading: false,<br>        errMsg:&#x27;&#x27;<br><br>      &#125;<br><br>    &#125;<br>  &#125;,<br>  mounted() &#123;<br>    this.$bus.$on(&quot;userListData&quot;, (userListData)=&gt;&#123;<br>      // 使用 es6 语法，替换不同的属性<br>      this.userListData = &#123;...this.userListData, ...userListData&#125;;<br>    &#125;)<br>  &#125;<br>&#125;<br>&lt;/script&gt;<br><br>&lt;style scoped&gt;<br>  .album &#123;<br>    min-height: 50rem; /* Can be removed; just added for demo purposes */<br>    padding-top: 3rem;<br>    padding-bottom: 3rem;<br>    background-color: #f7f7f7;<br>  &#125;<br><br>  .card &#123;<br>    float: left;<br>    width: 33.333%;<br>    padding: .75rem;<br>    margin-bottom: 2rem;<br>    border: 1px solid #efefef;<br>    text-align: center;<br>  &#125;<br><br>  .card &gt; img &#123;<br>    margin-bottom: .75rem;<br>    border-radius: 100px;<br>  &#125;<br><br>  .card-text &#123;<br>    font-size: 85%;<br>  &#125;<br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>



<h2 id="20-插槽"><a href="#20-插槽" class="headerlink" title="20.插槽"></a>20.插槽</h2><ol>
<li><p>作用：让父组件可以向子组件指定位置<strong>插入 html 结构</strong>，也是一种组件间通信的方式，适用于 <strong style="color:red">父组件 ===&gt; 子组件</strong> 。</p>
</li>
<li><p>分类：默认插槽、具名插槽、作用域插槽</p>
</li>
<li><p>使用方式：</p>
<ol>
<li><p>默认插槽：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs vue">父组件中：<br>        &lt;Category&gt;<br>           &lt;div&gt;html结构1&lt;/div&gt;<br>        &lt;/Category&gt;<br>子组件中：<br>        &lt;template&gt;<br>            &lt;div&gt;<br>               &lt;!-- 定义插槽 --&gt;<br>               &lt;slot&gt;插槽默认内容...&lt;/slot&gt;<br>            &lt;/div&gt;<br>        &lt;/template&gt;<br></code></pre></td></tr></table></figure></li>
<li><p>具名插槽：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs vue">父组件中：<br>        &lt;Category&gt;<br>            &lt;template slot=&quot;center&quot;&gt;<br>              &lt;div&gt;html结构1&lt;/div&gt;<br>            &lt;/template&gt;<br><br>            &lt;template v-slot:footer&gt;<br>               &lt;div&gt;html结构2&lt;/div&gt;<br>            &lt;/template&gt;<br>        &lt;/Category&gt;<br>子组件中：<br>        &lt;template&gt;<br>            &lt;div&gt;<br>               &lt;!-- 定义插槽 --&gt;<br>               &lt;slot name=&quot;center&quot;&gt;插槽默认内容...&lt;/slot&gt;<br>               &lt;slot name=&quot;footer&quot;&gt;插槽默认内容...&lt;/slot&gt;<br>            &lt;/div&gt;<br>        &lt;/template&gt;<br></code></pre></td></tr></table></figure></li>
<li><p>作用域插槽：</p>
<ol>
<li><p>理解：<span style="color:red">数据在组件的自身，但根据数据生成的结构需要组件的使用者来决定。</span>（games数据在Category组件中，但使用数据所遍历出来的结构由App组件决定）</p>
</li>
<li><p>具体编码：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><code class="hljs vue">父组件中：<br>		&lt;Category&gt;<br>			&lt;template scope=&quot;scopeData&quot;&gt;<br>				&lt;!-- 生成的是ul列表 --&gt;<br>				&lt;ul&gt;<br>					&lt;li v-for=&quot;g in scopeData.games&quot; :key=&quot;g&quot;&gt;&#123;&#123;g&#125;&#125;&lt;/li&gt;<br>				&lt;/ul&gt;<br>			&lt;/template&gt;<br>		&lt;/Category&gt;<br><br>		&lt;Category&gt;<br>			&lt;template slot-scope=&quot;scopeData&quot;&gt;<br>				&lt;!-- 生成的是h4标题 --&gt;<br>				&lt;h4 v-for=&quot;g in scopeData.games&quot; :key=&quot;g&quot;&gt;&#123;&#123;g&#125;&#125;&lt;/h4&gt;<br>			&lt;/template&gt;<br>		&lt;/Category&gt;<br>子组件中：<br>        &lt;template&gt;<br>            &lt;div&gt;<br>                &lt;slot :games=&quot;games&quot;&gt;&lt;/slot&gt;<br>            &lt;/div&gt;<br>        &lt;/template&gt;<br>		<br>        &lt;script&gt;<br>            export default &#123;<br>                name:&#x27;Category&#x27;,<br>                props:[&#x27;title&#x27;],<br>                //数据在子组件自身<br>                data() &#123;<br>                    return &#123;<br>                        games:[&#x27;红色警戒&#x27;,&#x27;穿越火线&#x27;,&#x27;劲舞团&#x27;,&#x27;超级玛丽&#x27;]<br>                    &#125;<br>                &#125;,<br>            &#125;<br>        &lt;/script&gt;<br></code></pre></td></tr></table></figure></li>
</ol>
</li>
</ol>
</li>
</ol>
<p>Category.vue</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;div class=&quot;category&quot;&gt;<br>    &lt;h2&gt;学生姓名&lt;/h2&gt;<br>    &lt;slot :students=&quot;students&quot;&gt;&lt;/slot&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>  export default &#123;<br>    name: &quot;Category&quot;,<br>    data() &#123;<br>      return &#123;<br>        students: [&#x27;张三&#x27;, &#x27;李四&#x27;, &#x27;王五&#x27;, &#x27;赵六&#x27;]<br>      &#125;<br>    &#125;<br>  &#125;<br>&lt;/script&gt;<br><br>&lt;style scoped&gt;<br>  .category&#123;<br>    background-color: skyblue;<br>    width: 200px;<br>    height: 300px;<br>  &#125;<br>  h3&#123;<br>    text-align: center;<br>    background-color: orange;<br>  &#125;<br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>

<p>App.vue</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;div class=&quot;container&quot;&gt;<br>    &lt;Category&gt;<br>      &lt;template slot-scope=&quot;studentList&quot;&gt;<br>        &lt;!-- 使用无序列表 --&gt;<br>        &lt;ul&gt;<br>          &lt;li v-for=&quot;(s,index) in studentList.students&quot; :key=&quot;index&quot;&gt;&#123;&#123;s&#125;&#125;&lt;/li&gt;<br>        &lt;/ul&gt;<br>      &lt;/template&gt;<br>    &lt;/Category&gt;<br><br>    &lt;Category&gt;<br>      &lt;template slot-scope=&quot;studentList&quot;&gt;<br>        &lt;!-- 使用有序列表 --&gt;<br>        &lt;ol&gt;<br>          &lt;li v-for=&quot;(s,index) in studentList.students&quot; :key=&quot;index&quot;&gt;&#123;&#123;s&#125;&#125;&lt;/li&gt;<br>        &lt;/ol&gt;<br>      &lt;/template&gt;<br>    &lt;/Category&gt;<br><br>    &lt;Category&gt;<br>      &lt;template slot-scope=&quot;studentList&quot;&gt;<br>        &lt;!-- 使用 h3 --&gt;<br>        &lt;h3 v-for=&quot;(s,index) in studentList.students&quot; :key=&quot;index&quot;&gt;&#123;&#123;s&#125;&#125;&lt;/h3&gt;<br>      &lt;/template&gt;<br>    &lt;/Category&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>// 引入组件<br>import Category from &quot;./components/Category&quot;;<br><br><br>export default &#123;<br>  name: &quot;App&quot;,<br>  components:&#123;Category&#125;<br><br>&#125;<br>&lt;/script&gt;<br><br>&lt;style&gt;<br>  .container&#123;<br>    display: flex;<br>    justify-content: space-around;<br>  &#125;<br>&lt;/style&gt;<br></code></pre></td></tr></table></figure>

<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210807/image.3gk2ejvvp6g0.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<h2 id="21-vuex"><a href="#21-vuex" class="headerlink" title="21.vuex"></a>21.vuex</h2><h3 id="21-1-概念"><a href="#21-1-概念" class="headerlink" title="21.1 概念"></a>21.1 概念</h3><p>​        在 Vue 中<strong>实现集中式状态（数据）管理</strong>的一个 Vue 插件，对 vue 应用中多个组件的共享状态进行集中式的管理（读/写），也是一种组件间通信的方式，且适用于任意组件间通信。</p>
<p><strong>原理图：</strong></p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210807/vuex.2ojegdkdlzy0.png" srcset="/img/loading.gif" lazyload alt="vuex"></p>
<p><a target="_blank" rel="noopener" href="https://vuex.vuejs.org/zh/">官方介绍</a></p>
<h3 id="21-2-何时使用？"><a href="#21-2-何时使用？" class="headerlink" title="21.2 何时使用？"></a>21.2 何时使用？</h3><p>​        多个组件需要共享数据时</p>
<h3 id="21-3-搭建vuex环境"><a href="#21-3-搭建vuex环境" class="headerlink" title="21.3 搭建vuex环境"></a>21.3 搭建vuex环境</h3><ol>
<li><p>创建文件：<code>src/store/index.js</code></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">//引入Vue核心库</span><br><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;vue&#x27;</span><br><span class="hljs-comment">//引入Vuex</span><br><span class="hljs-keyword">import</span> Vuex <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;vuex&#x27;</span><br><span class="hljs-comment">//应用Vuex插件</span><br>Vue.use(Vuex)<br><br><span class="hljs-comment">//准备actions对象——响应组件中用户的动作</span><br><span class="hljs-keyword">const</span> actions = &#123;&#125;<br><span class="hljs-comment">//准备mutations对象——修改state中的数据</span><br><span class="hljs-keyword">const</span> mutations = &#123;&#125;<br><span class="hljs-comment">//准备state对象——保存具体的数据</span><br><span class="hljs-keyword">const</span> state = &#123;&#125;<br><br><span class="hljs-comment">//创建并暴露store</span><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">new</span> Vuex.Store(&#123;<br>	actions,<br>	mutations,<br>	state<br>&#125;)<br></code></pre></td></tr></table></figure></li>
<li><p>在<code>main.js</code>中创建vm时传入<code>store</code>配置项</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs js">......<br><span class="hljs-comment">//引入store</span><br><span class="hljs-keyword">import</span> store <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;./store&#x27;</span><br>......<br><br><span class="hljs-comment">//创建vm</span><br><span class="hljs-keyword">new</span> Vue(&#123;<br>	<span class="hljs-attr">el</span>:<span class="hljs-string">&#x27;#app&#x27;</span>,<br>	<span class="hljs-attr">render</span>: <span class="hljs-function"><span class="hljs-params">h</span> =&gt;</span> h(App),<br>	store<br>&#125;)<br></code></pre></td></tr></table></figure></li>
</ol>
<h3 id="21-4-基本使用"><a href="#21-4-基本使用" class="headerlink" title="21.4 基本使用"></a>21.4 基本使用</h3><ol>
<li><p>初始化数据、配置<code>actions</code>、配置<code>mutations</code>，操作文件<code>store.js</code></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">//引入Vue核心库</span><br><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;vue&#x27;</span><br><span class="hljs-comment">//引入Vuex</span><br><span class="hljs-keyword">import</span> Vuex <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;vuex&#x27;</span><br><span class="hljs-comment">//引用Vuex</span><br>Vue.use(Vuex)<br><br><span class="hljs-keyword">const</span> actions = &#123;<br>    <span class="hljs-comment">//响应组件中加的动作</span><br>	<span class="hljs-function"><span class="hljs-title">jia</span>(<span class="hljs-params">context,value</span>)</span>&#123;<br>		<span class="hljs-comment">// console.log(&#x27;actions中的jia被调用了&#x27;,miniStore,value)</span><br>		context.commit(<span class="hljs-string">&#x27;JIA&#x27;</span>,value)<br>	&#125;,<br>&#125;<br><br><span class="hljs-keyword">const</span> mutations = &#123;<br>    <span class="hljs-comment">//执行加</span><br>	<span class="hljs-function"><span class="hljs-title">JIA</span>(<span class="hljs-params">state,value</span>)</span>&#123;<br>		<span class="hljs-comment">// console.log(&#x27;mutations中的JIA被调用了&#x27;,state,value)</span><br>		state.sum += value<br>	&#125;<br>&#125;<br><br><span class="hljs-comment">//初始化数据</span><br><span class="hljs-keyword">const</span> state = &#123;<br>   <span class="hljs-attr">sum</span>:<span class="hljs-number">0</span><br>&#125;<br><br><span class="hljs-comment">//创建并暴露store</span><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">new</span> Vuex.Store(&#123;<br>	actions,<br>	mutations,<br>	state,<br>&#125;)<br></code></pre></td></tr></table></figure></li>
<li><p>组件中读取 vuex 中的数据：<code>$store.state.sum</code></p>
</li>
<li><p>组件中修改 vuex 中的数据：<code>$store.dispatch(&#39;action中的方法名&#39;,数据)</code> 或 <code>$store.commit(&#39;mutations中的方法名&#39;,数据)</code></p>
<blockquote>
<p> 备注：若没有网络请求或其他业务逻辑，组件中也可以越过 actions，即不写<code>dispatch</code>，直接编写<code>commit</code></p>
</blockquote>
</li>
<li><p><code>actions</code> 中写方法接受到的参数</p>
</li>
</ol>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210807/image.s3qeuec97ps.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<ol start="5">
<li><code>mutations</code> 中写方法接受到的参数</li>
</ol>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210807/image.3g79lc4w5zy0.png" srcset="/img/loading.gif" lazyload alt="image"></p>
<h3 id="21-5-getters的使用"><a href="#21-5-getters的使用" class="headerlink" title="21.5 getters的使用"></a>21.5 getters的使用</h3><ol>
<li><p>概念：当 state 中的数据需要经过加工后再使用时，可以使用 getters 加工，可以看做是组件中的计算属性。</p>
</li>
<li><p>在<code>store.js</code>中追加<code>getters</code>配置</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs js">......<br><br><span class="hljs-keyword">const</span> getters = &#123;<br>	<span class="hljs-function"><span class="hljs-title">bigSum</span>(<span class="hljs-params">state</span>)</span>&#123;<br>		<span class="hljs-keyword">return</span> state.sum * <span class="hljs-number">10</span><br>	&#125;<br>&#125;<br><br><span class="hljs-comment">//创建并暴露store</span><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">new</span> Vuex.Store(&#123;<br>	......<br>	getters<br>&#125;)<br></code></pre></td></tr></table></figure></li>
<li><p>组件中读取数据：<code>$store.getters.bigSum</code></p>
</li>
</ol>
<h3 id="21-6-四个map方法的使用"><a href="#21-6-四个map方法的使用" class="headerlink" title="21.6 四个map方法的使用"></a>21.6 四个map方法的使用</h3><ol>
<li><p><strong>mapState 方法：</strong>用于帮助我们映射<code>state</code>中的数据为计算属性</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs js">computed: &#123;<br>    <span class="hljs-comment">//借助mapState生成计算属性：sum、school、subject（对象写法）</span><br>     ...mapState(&#123;<span class="hljs-attr">sum</span>:<span class="hljs-string">&#x27;sum&#x27;</span>,<span class="hljs-attr">school</span>:<span class="hljs-string">&#x27;school&#x27;</span>,<span class="hljs-attr">subject</span>:<span class="hljs-string">&#x27;subject&#x27;</span>&#125;),<br>         <br>    <span class="hljs-comment">//借助mapState生成计算属性：sum、school、subject（数组写法）</span><br>    ...mapState([<span class="hljs-string">&#x27;sum&#x27;</span>,<span class="hljs-string">&#x27;school&#x27;</span>,<span class="hljs-string">&#x27;subject&#x27;</span>]),<br>&#125;,<br></code></pre></td></tr></table></figure></li>
<li><p><strong>mapGetters 方法：</strong>用于帮助我们映射<code>getters</code>中的数据为计算属性</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs js">computed: &#123;<br>    <span class="hljs-comment">//借助mapGetters生成计算属性：bigSum（对象写法）</span><br>    ...mapGetters(&#123;<span class="hljs-attr">bigSum</span>:<span class="hljs-string">&#x27;bigSum&#x27;</span>&#125;),<br><br>    <span class="hljs-comment">//借助mapGetters生成计算属性：bigSum（数组写法）</span><br>    ...mapGetters([<span class="hljs-string">&#x27;bigSum&#x27;</span>])<br>&#125;,<br></code></pre></td></tr></table></figure></li>
<li><p><strong>mapActions 方法：</strong>用于帮助我们生成与<code>actions</code>对话的方法，即：包含<code>$store.dispatch(xxx)</code>的函数</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs js">methods:&#123;<br>    <span class="hljs-comment">//靠mapActions生成方法名为 incrementOdd、incrementWait（对象形式）</span><br>    ...mapActions(&#123;<span class="hljs-attr">incrementOdd</span>:<span class="hljs-string">&#x27;jiaOdd&#x27;</span>,<span class="hljs-attr">incrementWait</span>:<span class="hljs-string">&#x27;jiaWait&#x27;</span>&#125;)<br><br>    <span class="hljs-comment">//靠mapActions生成方法名为 jiaOdd、jiaWait（数组形式）</span><br>    ...mapActions([<span class="hljs-string">&#x27;jiaOdd&#x27;</span>,<span class="hljs-string">&#x27;jiaWait&#x27;</span>])<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li><p><strong>mapMutations 方法：</strong>用于帮助我们生成与<code>mutations</code>对话的方法，即：包含<code>$store.commit(xxx)</code>的函数</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs js">methods:&#123;<br>    <span class="hljs-comment">//靠mapActions生成方法名为increment、decrement（对象形式）</span><br>    ...mapMutations(&#123;<span class="hljs-attr">increment</span>:<span class="hljs-string">&#x27;JIA&#x27;</span>,<span class="hljs-attr">decrement</span>:<span class="hljs-string">&#x27;JIAN&#x27;</span>&#125;),<br>    <br>    <span class="hljs-comment">//靠mapMutations生成方法名为：JIA、JIAN（数组形式）</span><br>    ...mapMutations([<span class="hljs-string">&#x27;JIA&#x27;</span>,<span class="hljs-string">&#x27;JIAN&#x27;</span>]),<br>&#125;<br></code></pre></td></tr></table></figure></li>
</ol>
<blockquote>
<p>备注：mapActions 与 mapMutations 使用时，若需要传递参数需要：<strong>在模板中绑定事件时传递好参数</strong>，否则参数是<strong>事件对象</strong>。</p>
</blockquote>
<h3 id="21-7-模块化-命名空间"><a href="#21-7-模块化-命名空间" class="headerlink" title="21.7 模块化+命名空间"></a>21.7 模块化+命名空间</h3><ol>
<li><p>目的：让代码更好维护，让多种数据分类更加明确。</p>
</li>
<li><p>修改<code>store.js</code></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> count = &#123;<br>  <span class="hljs-attr">namespaced</span>:<span class="hljs-literal">true</span>,<span class="hljs-comment">//开启命名空间</span><br>  <span class="hljs-attr">state</span>:&#123;<span class="hljs-attr">x</span>:<span class="hljs-number">1</span>&#125;,<br>  <span class="hljs-attr">mutations</span>: &#123; ... &#125;,<br>  <span class="hljs-attr">actions</span>: &#123; ... &#125;,<br>  <span class="hljs-attr">getters</span>: &#123;<br>    <span class="hljs-function"><span class="hljs-title">bigSum</span>(<span class="hljs-params">state</span>)</span>&#123;<br>       <span class="hljs-keyword">return</span> state.sum * <span class="hljs-number">10</span><br>    &#125;<br>  &#125;<br>&#125;<br><br><span class="hljs-keyword">const</span> count2 = &#123;<br>  <span class="hljs-attr">namespaced</span>:<span class="hljs-literal">true</span>,<span class="hljs-comment">//开启命名空间</span><br>  <span class="hljs-attr">state</span>:&#123; ... &#125;,<br>  <span class="hljs-attr">mutations</span>: &#123; ... &#125;,<br>  <span class="hljs-attr">actions</span>: &#123; ... &#125;<br>&#125;<br><br><span class="hljs-keyword">const</span> store = <span class="hljs-keyword">new</span> Vuex.Store(&#123;<br>  <span class="hljs-attr">modules</span>: &#123;<br>  	<span class="hljs-attr">count</span>: count,<br>    <span class="hljs-attr">count2</span>: count2<br>  &#125;<br>&#125;)<br></code></pre></td></tr></table></figure></li>
<li><p>开启命名空间后，组件中读取 state 数据：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">//方式一：自己直接读取</span><br><span class="hljs-attr">computed</span>: &#123;<br>    <span class="hljs-function"><span class="hljs-title">sum</span>(<span class="hljs-params"></span>)</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.$store.state.count.sum;<br>    &#125;<br>&#125;<br><span class="hljs-comment">//方式二：借助 mapState 读取：</span><br><span class="hljs-attr">computed</span>: &#123;<br>    ...mapState(<span class="hljs-string">&#x27;count2&#x27;</span>, [<span class="hljs-string">&#x27;sum&#x27;</span>]),<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li><p>开启命名空间后，组件中读取 getters 数据：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">//方式一：自己直接读取</span><br><span class="hljs-attr">computed</span>: &#123;<br>    <span class="hljs-function"><span class="hljs-title">sumAfterMul</span>(<span class="hljs-params"></span>)</span> &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.$store.getters[<span class="hljs-string">&#x27;count/sumAfterMul&#x27;</span>];<br>    &#125;<br>&#125;<br><span class="hljs-comment">//方式二：借助mapGetters读取：</span><br><span class="hljs-attr">computed</span>: &#123;<br>    ...mapGetters(<span class="hljs-string">&#x27;count2&#x27;</span>, [<span class="hljs-string">&#x27;sumAfterMul&#x27;</span>]),<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li><p>开启命名空间后，组件中调用 dispatch</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">//方式一：自己调用 dispatch</span><br><span class="hljs-attr">methods</span>: &#123;<br>    decrement () &#123;<br>        <span class="hljs-built_in">this</span>.$store.dispatch(<span class="hljs-string">&quot;count/sub&quot;</span>, <span class="hljs-built_in">this</span>.number);<br>    &#125;,<br>    <span class="hljs-function"><span class="hljs-title">incrementOdd</span>(<span class="hljs-params"></span>)</span> &#123;<br>        <span class="hljs-built_in">this</span>.$store.dispatch(<span class="hljs-string">&quot;count/addOdd&quot;</span>, <span class="hljs-built_in">this</span>.number);<br>    &#125;,<br>    <span class="hljs-function"><span class="hljs-title">incrementWait</span>(<span class="hljs-params"></span>)</span> &#123;<br>        <span class="hljs-built_in">this</span>.$store.dispatch(<span class="hljs-string">&quot;count/addWait&quot;</span>, <span class="hljs-built_in">this</span>.number);<br>    &#125;,<br>&#125;<br><span class="hljs-comment">//方式二：借助 mapActions：</span><br><span class="hljs-attr">methods</span>: &#123;<br>    ...mapActions(<span class="hljs-string">&#x27;count2&#x27;</span>, &#123;<span class="hljs-attr">decrement</span>: <span class="hljs-string">&#x27;sub&#x27;</span>, <span class="hljs-attr">incrementOdd</span>:<span class="hljs-string">&#x27;addOdd&#x27;</span>,<span class="hljs-attr">incrementWait</span>:<span class="hljs-string">&#x27;addWait&#x27;</span>&#125;)<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li><p>开启命名空间后，组件中调用 commit</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">//方式一：自己直接 commit</span><br><span class="hljs-attr">methods</span>: &#123;<br>    <span class="hljs-function"><span class="hljs-title">increment</span>(<span class="hljs-params"></span>)</span> &#123;<br>        <span class="hljs-built_in">this</span>.$store.commit(<span class="hljs-string">&quot;count/ADD&quot;</span>, <span class="hljs-built_in">this</span>.number);<br>    &#125;<br>&#125;<br><span class="hljs-comment">//方式二：借助 mapMutations：</span><br><span class="hljs-attr">methods</span>: &#123;<br>    ...mapMutations(<span class="hljs-string">&#x27;count2&#x27;</span>,&#123;<span class="hljs-attr">increment</span>: <span class="hljs-string">&#x27;ADD&#x27;</span>&#125;),<br>&#125;<br></code></pre></td></tr></table></figure></li>
</ol>
<h2 id="22-路由"><a href="#22-路由" class="headerlink" title="22.路由"></a>22.路由</h2><ol>
<li>理解： 一个路由（route）就是一组映射关系（key - value），多个路由需要路由器（router）进行管理。</li>
<li>前端路由：key 是路径，value 是组件。</li>
</ol>
<h3 id="22-1-基本使用"><a href="#22-1-基本使用" class="headerlink" title="22.1 基本使用"></a>22.1 基本使用</h3><ol>
<li><p>安装 vue-router，命令：<code>npm i vue-router</code></p>
</li>
<li><p>应用插件：<code>Vue.use(VueRouter)</code></p>
</li>
<li><p>编写 router 配置项:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">//引入VueRouter</span><br><span class="hljs-keyword">import</span> VueRouter <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;vue-router&#x27;</span><br><span class="hljs-comment">//引入路由组件</span><br><span class="hljs-keyword">import</span> About <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;../components/About&#x27;</span><br><span class="hljs-keyword">import</span> Home <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;../components/Home&#x27;</span><br><br><span class="hljs-comment">//创建router实例对象，去管理一组一组的路由规则</span><br><span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> VueRouter(&#123;<br>	<span class="hljs-attr">routes</span>:[<br>		&#123;<br>			<span class="hljs-attr">path</span>:<span class="hljs-string">&#x27;/about&#x27;</span>,<br>			<span class="hljs-attr">component</span>:About<br>		&#125;,<br>		&#123;<br>			<span class="hljs-attr">path</span>:<span class="hljs-string">&#x27;/home&#x27;</span>,<br>			<span class="hljs-attr">component</span>:Home<br>		&#125;<br>	]<br>&#125;)<br><br><span class="hljs-comment">//暴露router</span><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> router<br></code></pre></td></tr></table></figure></li>
<li><p>在 main.js 中配置路由</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;vue&quot;</span>;<br><span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;./App&quot;</span>;<br><span class="hljs-comment">// 引入 vueRouter</span><br><span class="hljs-keyword">import</span> vueRouter <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;vue-router&quot;</span>;<br><span class="hljs-comment">// 引入路由器</span><br><span class="hljs-keyword">import</span> router <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;./router/index&quot;</span>;<br><br>Vue.config.productionTip = <span class="hljs-literal">false</span><br><br><span class="hljs-comment">// 使用路由插件</span><br>Vue.use(vueRouter);<br><br><span class="hljs-keyword">new</span> Vue(&#123;<br>    <span class="hljs-attr">el</span>: <span class="hljs-string">&#x27;#app&#x27;</span>,<br>    <span class="hljs-attr">render</span>: <span class="hljs-function"><span class="hljs-params">h</span> =&gt;</span> h(App),<br>    <span class="hljs-comment">// 配置路由</span><br>    <span class="hljs-attr">router</span>: router<br>&#125;)<br></code></pre></td></tr></table></figure></li>
<li><p>实现切换（active-class可配置高亮样式）</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;router-link active-class=&quot;active&quot; to=&quot;/about&quot;&gt;About&lt;/router-link&gt;<br></code></pre></td></tr></table></figure></li>
<li><p>指定展示位置</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;router-view&gt;&lt;/router-view&gt;<br></code></pre></td></tr></table></figure></li>
<li><p>结果</p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210808/QQ%E5%BD%95%E5%B1%8F20210808101448.61kc2hbqd240.gif" srcset="/img/loading.gif" lazyload alt="QQ录屏20210808101448"></p>
</li>
</ol>
<h3 id="22-2-几个注意点"><a href="#22-2-几个注意点" class="headerlink" title="22.2 几个注意点"></a>22.2 几个注意点</h3><ol>
<li><p>路由组件通常存放在 <code>pages</code> 文件夹，一般组件通常存放在 <code>components</code> 文件夹。</p>
</li>
<li><p>通过切换，“隐藏” 了的路由组件，<strong>默认是被销毁掉的</strong>，需要的时候再去挂载。</p>
</li>
<li><p>每个组件都有自己的 <code>$route</code> 属性，里面存储着自己的路由信息。</p>
<p><img src="https://cdn.jsdelivr.net/gh/yechen-ops/image-hosting@master/20210808/image.2sxwd2di1ws.png" srcset="/img/loading.gif" lazyload alt="image"></p>
</li>
<li><p>整个应用只有一个 router，可以通过组件的 <code>$router</code> 属性获取到。</p>
</li>
</ol>
<h3 id="22-3-多级路由（多级路由）"><a href="#22-3-多级路由（多级路由）" class="headerlink" title="22.3 多级路由（多级路由）"></a>22.3 多级路由（多级路由）</h3><ol>
<li><p>配置路由规则，使用 children 配置项：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs js">routes:[<br>	&#123;<br>		<span class="hljs-attr">path</span>:<span class="hljs-string">&#x27;/about&#x27;</span>,<br>		<span class="hljs-attr">component</span>:About,<br>	&#125;,<br>	&#123;<br>		<span class="hljs-attr">path</span>:<span class="hljs-string">&#x27;/home&#x27;</span>,<br>		<span class="hljs-attr">component</span>:Home,<br>		<span class="hljs-attr">children</span>:[ <span class="hljs-comment">//通过children配置子级路由</span><br>			&#123;<br>				<span class="hljs-attr">path</span>:<span class="hljs-string">&#x27;news&#x27;</span>, <span class="hljs-comment">//此处一定不要写：/news</span><br>				<span class="hljs-attr">component</span>:News<br>			&#125;,<br>			&#123;<br>				<span class="hljs-attr">path</span>:<span class="hljs-string">&#x27;message&#x27;</span>,<span class="hljs-comment">//此处一定不要写：/message</span><br>				<span class="hljs-attr">component</span>:Message<br>			&#125;<br>		]<br>	&#125;<br>]<br></code></pre></td></tr></table></figure></li>
<li><p>跳转（要写完整路径）：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;router-link to=&quot;/home/news&quot;&gt;News&lt;/router-link&gt;<br></code></pre></td></tr></table></figure></li>
</ol>
<h3 id="22-4-路由的-query-参数"><a href="#22-4-路由的-query-参数" class="headerlink" title="22.4 路由的 query 参数"></a>22.4 路由的 query 参数</h3><ol>
<li><p>传递参数</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;!-- 跳转并携带 query 参数，to 的字符串写法 --&gt;<br>&lt;router-link :to=&quot;/home/message/detail?id=666&amp;title=你好&quot;&gt;跳转&lt;/router-link&gt;<br>				<br>&lt;!-- 跳转并携带query参数，to的对象写法 --&gt;<br>&lt;router-link <br>	:to=&quot;&#123;<br>		path:&#x27;/home/message/detail&#x27;,<br>		query:&#123;<br>		   id:666,<br>            title:&#x27;你好&#x27;<br>		&#125;<br>	&#125;&quot;<br>&gt;跳转&lt;/router-link&gt;<br></code></pre></td></tr></table></figure></li>
<li><p>接收参数：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs js">$route.query.id<br>$route.query.title<br></code></pre></td></tr></table></figure></li>
</ol>
<h3 id="22-5-命名路由"><a href="#22-5-命名路由" class="headerlink" title="22.5 命名路由"></a>22.5 命名路由</h3><ol>
<li><p>作用：可以简化路由的跳转。</p>
</li>
<li><p>如何使用</p>
<ol>
<li><p>给路由命名：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs js">&#123;<br>	<span class="hljs-attr">path</span>:<span class="hljs-string">&#x27;/demo&#x27;</span>,<br>	<span class="hljs-attr">component</span>:Demo,<br>	<span class="hljs-attr">children</span>:[<br>		&#123;<br>			<span class="hljs-attr">path</span>:<span class="hljs-string">&#x27;test&#x27;</span>,<br>			<span class="hljs-attr">component</span>:Test,<br>			<span class="hljs-attr">children</span>:[<br>				&#123;<br>                    <span class="hljs-attr">name</span>:<span class="hljs-string">&#x27;hello&#x27;</span> <span class="hljs-comment">//给路由命名</span><br>					<span class="hljs-attr">path</span>:<span class="hljs-string">&#x27;welcome&#x27;</span>,<br>					<span class="hljs-attr">component</span>:Hello,<br>				&#125;<br>			]<br>		&#125;<br>	]<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li><p>简化跳转：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;!--简化前，需要写完整的路径 --&gt;<br>&lt;router-link to=&quot;/demo/test/welcome&quot;&gt;跳转&lt;/router-link&gt;<br><br>&lt;!--简化后，直接通过名字跳转 --&gt;<br>&lt;router-link :to=&quot;&#123;name:&#x27;hello&#x27;&#125;&quot;&gt;跳转&lt;/router-link&gt;<br><br>&lt;!--简化写法配合传递参数 --&gt;<br>&lt;router-link <br>	:to=&quot;&#123;<br>		name:&#x27;hello&#x27;,<br>		query:&#123;<br>		   id:666,<br>            title:&#x27;你好&#x27;<br>		&#125;<br>	&#125;&quot;<br>&gt;跳转&lt;/router-link&gt;<br></code></pre></td></tr></table></figure></li>
</ol>
</li>
</ol>
<h3 id="22-6-路由的params参数"><a href="#22-6-路由的params参数" class="headerlink" title="22.6 路由的params参数"></a>22.6 路由的params参数</h3><ol>
<li><p>配置路由，声明接收params参数</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs js">&#123;<br>	<span class="hljs-attr">path</span>:<span class="hljs-string">&#x27;/home&#x27;</span>,<br>	<span class="hljs-attr">component</span>:Home,<br>	<span class="hljs-attr">children</span>:[<br>		&#123;<br>			<span class="hljs-attr">path</span>:<span class="hljs-string">&#x27;news&#x27;</span>,<br>			<span class="hljs-attr">component</span>:News<br>		&#125;,<br>		&#123;<br>			<span class="hljs-attr">component</span>:Message,<br>			<span class="hljs-attr">children</span>:[<br>				&#123;<br>					<span class="hljs-attr">name</span>:<span class="hljs-string">&#x27;xiangqing&#x27;</span>,<br>					<span class="hljs-attr">path</span>:<span class="hljs-string">&#x27;detail/:id/:title&#x27;</span>, <span class="hljs-comment">//使用占位符声明接收params参数</span><br>					<span class="hljs-attr">component</span>:Detail<br>				&#125;<br>			]<br>		&#125;<br>	]<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li><p>传递参数</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;!-- 跳转并携带params参数，to的字符串写法 --&gt;<br>&lt;router-link :to=&quot;/home/message/detail/666/你好&quot;&gt;跳转&lt;/router-link&gt;<br>				<br>&lt;!-- 跳转并携带params参数，to的对象写法 --&gt;<br>&lt;router-link <br>	:to=&quot;&#123;<br>		name:&#x27;xiangqing&#x27;,<br>		params:&#123;<br>		   id:666,<br>            title:&#x27;你好&#x27;<br>		&#125;<br>	&#125;&quot;<br>&gt;跳转&lt;/router-link&gt;<br></code></pre></td></tr></table></figure>

<blockquote>
<p>特别注意：路由携带 params 参数时，若使用 to 的对象写法，则不能使用 path 配置项，必须使用name 配置！</p>
</blockquote>
</li>
<li><p>接收参数：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs js">$route.params.id<br>$route.params.title<br></code></pre></td></tr></table></figure></li>
</ol>
<h3 id="22-7-路由的props配置"><a href="#22-7-路由的props配置" class="headerlink" title="22.7 路由的props配置"></a>22.7 路由的props配置</h3><p>​    作用：让路由组件更方便的收到参数</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs js">&#123;<br>	<span class="hljs-attr">name</span>:<span class="hljs-string">&#x27;xiangqing&#x27;</span>,<br>	<span class="hljs-attr">path</span>:<span class="hljs-string">&#x27;detail/:id&#x27;</span>,<br>	<span class="hljs-attr">component</span>:Detail,<br><br>	<span class="hljs-comment">//第一种写法：props值为对象，该对象中所有的key-value的组合最终都会通过props传给Detail组件</span><br>	<span class="hljs-comment">// props:&#123;a:900&#125;</span><br><br>	<span class="hljs-comment">//第二种写法：props值为布尔值，布尔值为true，则把路由收到的所有params参数通过props传给Detail组件</span><br>	<span class="hljs-comment">// props:true</span><br>	<br>	<span class="hljs-comment">//第三种写法：props值为函数，该函数返回的对象中每一组key-value都会通过props传给Detail组件，函数中会收到一个参数 $route</span><br>	<span class="hljs-function"><span class="hljs-title">props</span>(<span class="hljs-params">route</span>)</span>&#123;<br>		<span class="hljs-keyword">return</span> &#123;<br>			<span class="hljs-attr">id</span>:route.query.id,<br>			<span class="hljs-attr">title</span>:route.query.title<br>		&#125;<br>	&#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<h3 id="22-8-lt-router-link-gt-的replace属性"><a href="#22-8-lt-router-link-gt-的replace属性" class="headerlink" title="22.8 &lt;router-link&gt; 的replace属性"></a>22.8 <code>&lt;router-link&gt;</code> 的replace属性</h3><ol>
<li>作用：控制路由跳转时操作浏览器历史记录的模式</li>
<li>浏览器的历史记录有两种写入方式：分别为<code>push</code>和<code>replace</code>，<code>push</code>是追加历史记录，<code>replace</code>是替换当前记录。路由跳转时候默认为<code>push</code></li>
<li>如何开启<code>replace</code>模式：<code>&lt;router-link replace .......&gt;News&lt;/router-link&gt;</code></li>
</ol>
<h3 id="22-9-编程式路由导航"><a href="#22-9-编程式路由导航" class="headerlink" title="22.9 编程式路由导航"></a>22.9 编程式路由导航</h3><ol>
<li><p>作用：不借助<code>&lt;router-link&gt; </code>实现路由跳转，让路由跳转更加灵活</p>
</li>
<li><p>具体编码：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">//$router的两个API</span><br><span class="hljs-built_in">this</span>.$router.push(&#123;<br>	<span class="hljs-attr">name</span>:<span class="hljs-string">&#x27;xiangqing&#x27;</span>,<br>		<span class="hljs-attr">params</span>:&#123;<br>			<span class="hljs-attr">id</span>:xxx,<br>			<span class="hljs-attr">title</span>:xxx<br>		&#125;<br>&#125;)<br><br><span class="hljs-built_in">this</span>.$router.replace(&#123;<br>	<span class="hljs-attr">name</span>:<span class="hljs-string">&#x27;xiangqing&#x27;</span>,<br>		<span class="hljs-attr">params</span>:&#123;<br>			<span class="hljs-attr">id</span>:xxx,<br>			<span class="hljs-attr">title</span>:xxx<br>		&#125;<br>&#125;)<br><span class="hljs-built_in">this</span>.$router.forward() <span class="hljs-comment">//前进</span><br><span class="hljs-built_in">this</span>.$router.back() <span class="hljs-comment">//后退</span><br><span class="hljs-built_in">this</span>.$router.go() <span class="hljs-comment">//可前进也可后退</span><br></code></pre></td></tr></table></figure></li>
</ol>
<h3 id="22-10-缓存路由组件"><a href="#22-10-缓存路由组件" class="headerlink" title="22. 10 缓存路由组件"></a>22. 10 缓存路由组件</h3><ol>
<li><p>作用：让不展示的路由组件保持挂载，不被销毁。</p>
</li>
<li><p>具体编码：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;!-- include中写的是组件的 name 值，要包含多个组价时，使用 :include=&quot;[&#x27;a&#x27;, &#x27;b&#x27;, ...]&quot; --&gt;<br>&lt;keep-alive include=&quot;News&quot;&gt; <br>    &lt;router-view&gt;&lt;/router-view&gt;<br>&lt;/keep-alive&gt;<br></code></pre></td></tr></table></figure></li>
</ol>
<h3 id="22-11-两个新的生命周期钩子"><a href="#22-11-两个新的生命周期钩子" class="headerlink" title="22.11 两个新的生命周期钩子"></a>22.11 两个新的生命周期钩子</h3><ol>
<li>作用：路由组件所独有的两个钩子，用于捕获路由组件的激活状态。</li>
<li>具体名字：<ol>
<li><code>activated</code>路由组件被激活时触发。</li>
<li><code>deactivated</code>路由组件失活时触发。</li>
</ol>
</li>
</ol>
<h3 id="22-12-路由守卫"><a href="#22-12-路由守卫" class="headerlink" title="22.12 路由守卫"></a>22.12 路由守卫</h3><ol>
<li><p>作用：对路由进行权限控制</p>
</li>
<li><p>分类：全局守卫、独享守卫、组件内守卫</p>
</li>
<li><p>全局守卫:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">//全局前置守卫：初始化时执行、每次路由切换前执行</span><br>router.beforeEach(<span class="hljs-function">(<span class="hljs-params">to,<span class="hljs-keyword">from</span>,next</span>)=&gt;</span>&#123;<br>	<span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;beforeEach&#x27;</span>,to,<span class="hljs-keyword">from</span>)<br>	<span class="hljs-keyword">if</span>(to.meta.isAuth)&#123; <span class="hljs-comment">//判断当前路由是否需要进行权限控制</span><br>		<span class="hljs-keyword">if</span>(<span class="hljs-built_in">localStorage</span>.getItem(<span class="hljs-string">&#x27;school&#x27;</span>) === <span class="hljs-string">&#x27;atguigu&#x27;</span>)&#123; <span class="hljs-comment">//权限控制的具体规则</span><br>			next() <span class="hljs-comment">//放行</span><br>		&#125;<span class="hljs-keyword">else</span>&#123;<br>			alert(<span class="hljs-string">&#x27;暂无权限查看&#x27;</span>)<br>			<span class="hljs-comment">// next(&#123;name:&#x27;guanyu&#x27;&#125;)</span><br>		&#125;<br>	&#125;<span class="hljs-keyword">else</span>&#123;<br>		next() <span class="hljs-comment">//放行</span><br>	&#125;<br>&#125;)<br><br><span class="hljs-comment">//全局后置守卫：初始化时执行、每次路由切换后执行</span><br>router.afterEach(<span class="hljs-function">(<span class="hljs-params">to,<span class="hljs-keyword">from</span></span>)=&gt;</span>&#123;<br>	<span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;afterEach&#x27;</span>,to,<span class="hljs-keyword">from</span>)<br>	<span class="hljs-keyword">if</span>(to.meta.title)&#123; <br>		<span class="hljs-built_in">document</span>.title = to.meta.title <span class="hljs-comment">//修改网页的title</span><br>	&#125;<span class="hljs-keyword">else</span>&#123;<br>		<span class="hljs-built_in">document</span>.title = <span class="hljs-string">&#x27;vue_test&#x27;</span><br>	&#125;<br>&#125;)<br></code></pre></td></tr></table></figure></li>
<li><p>独享守卫:</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-function"><span class="hljs-title">beforeEnter</span>(<span class="hljs-params">to,<span class="hljs-keyword">from</span>,next</span>)</span>&#123;<br>	<span class="hljs-built_in">console</span>.log(<span class="hljs-string">&#x27;beforeEnter&#x27;</span>,to,<span class="hljs-keyword">from</span>)<br>	<span class="hljs-keyword">if</span>(to.meta.isAuth)&#123; <span class="hljs-comment">//判断当前路由是否需要进行权限控制</span><br>		<span class="hljs-keyword">if</span>(<span class="hljs-built_in">localStorage</span>.getItem(<span class="hljs-string">&#x27;school&#x27;</span>) === <span class="hljs-string">&#x27;atguigu&#x27;</span>)&#123;<br>			next()<br>		&#125;<span class="hljs-keyword">else</span>&#123;<br>			alert(<span class="hljs-string">&#x27;暂无权限查看&#x27;</span>)<br>			<span class="hljs-comment">// next(&#123;name:&#x27;guanyu&#x27;&#125;)</span><br>		&#125;<br>	&#125;<span class="hljs-keyword">else</span>&#123;<br>		next()<br>	&#125;<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li><p>组件内守卫：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">//进入守卫：通过路由规则，进入该组件时被调用</span><br>beforeRouteEnter (to, <span class="hljs-keyword">from</span>, next) &#123;<br>&#125;,<br><span class="hljs-comment">//离开守卫：通过路由规则，离开该组件时被调用</span><br>beforeRouteLeave (to, <span class="hljs-keyword">from</span>, next) &#123;<br>&#125;<br></code></pre></td></tr></table></figure></li>
</ol>
<h3 id="22-13-路由器的两种工作模式"><a href="#22-13-路由器的两种工作模式" class="headerlink" title="22.13 路由器的两种工作模式"></a>22.13 路由器的两种工作模式</h3><ol>
<li>对于一个 url 来说，什么是 hash 值？—— # 及其后面的内容就是 hash 值。</li>
<li>hash 值不会包含在 HTTP 请求中，即：hash 值不会带给服务器。</li>
<li>hash 模式：<ol>
<li>地址中永远带着 # 号，不美观 。</li>
<li>若以后将地址通过第三方手机 app 分享，若 app 校验严格，则地址会被标记为不合法。</li>
<li>兼容性较好。</li>
</ol>
</li>
<li>history 模式：<ol>
<li>地址干净，美观 。</li>
<li>兼容性和 hash 模式相比略差。</li>
<li>应用部署上线时需要后端人员支持，解决刷新页面服务端 404 的问题。</li>
</ol>
</li>
</ol>
<h2 id="23-Vue-组件库"><a href="#23-Vue-组件库" class="headerlink" title="23 Vue 组件库"></a>23 Vue 组件库</h2><h3 id="23-1-移动端常用-UI-组件库"><a href="#23-1-移动端常用-UI-组件库" class="headerlink" title="23.1 移动端常用 UI 组件库"></a>23.1 移动端常用 UI 组件库</h3><ol>
<li><p><strong>Vant：</strong> <a target="_blank" rel="noopener" href="https://youzan.github.io/vant">https://youzan.github.io/vant</a> </p>
</li>
<li><p><strong>Cube UI：</strong> <a target="_blank" rel="noopener" href="https://didi.github.io/cube-ui">https://didi.github.io/cube-ui</a> </p>
</li>
<li><p><strong>Mint UI：</strong><a target="_blank" rel="noopener" href="http://mint-ui.github.io/">http://mint-ui.github.io</a> </p>
</li>
</ol>
<h3 id="23-2-PC-端常用-UI-组件库"><a href="#23-2-PC-端常用-UI-组件库" class="headerlink" title="23.2 PC 端常用 UI 组件库"></a>23.2 PC 端常用 UI 组件库</h3><ol>
<li><p><strong>Element UI：</strong> <a target="_blank" rel="noopener" href="https://element.eleme.cn/">https://element.eleme.cn</a> </p>
</li>
<li><p><strong>IView UI：</strong> <a target="_blank" rel="noopener" href="https://www.iviewui.com/">https://www.iviewui.com</a></p>
</li>
</ol>
<h3 id="23-3-使用-Element-UI"><a href="#23-3-使用-Element-UI" class="headerlink" title="23.3 使用 Element UI"></a>23.3 使用 Element UI</h3><p><a target="_blank" rel="noopener" href="https://element.eleme.cn/#/zh-CN/component/installation">参考官方手册</a></p>
<p>有个坑：按需引入时配置 <code>babel.config.js</code> （文档中是 <code>.babelrc</code>）应该配置为：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-built_in">module</span>.exports = &#123;<br>  <span class="hljs-attr">presets</span>: [<br>    <span class="hljs-string">&#x27;@vue/cli-plugin-babel/preset&#x27;</span>,<br>    [<span class="hljs-string">&quot;@babel/preset-env&quot;</span>, &#123; <span class="hljs-string">&quot;modules&quot;</span>: <span class="hljs-literal">false</span> &#125;]<br>  ],<br>  <span class="hljs-string">&quot;plugins&quot;</span>: [<br>    [<br>      <span class="hljs-string">&quot;component&quot;</span>,<br>      &#123;<br>        <span class="hljs-string">&quot;libraryName&quot;</span>: <span class="hljs-string">&quot;element-ui&quot;</span>,<br>        <span class="hljs-string">&quot;styleLibraryName&quot;</span>: <span class="hljs-string">&quot;theme-chalk&quot;</span><br>      &#125;<br>    ]<br>  ]<br>&#125;<br></code></pre></td></tr></table></figure>




            </div>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                  <div class="post-meta mr-3">
                    <i class="iconfont icon-category"></i>
                    
                      <a class="hover-with-bg" href="/categories/%E5%89%8D%E7%AB%AF/">前端</a>
                    
                      <a class="hover-with-bg" href="/categories/%E5%89%8D%E7%AB%AF/Vue/">Vue</a>
                    
                  </div>
                
                
                  <div class="post-meta">
                    <i class="iconfont icon-tags"></i>
                    
                      <a class="hover-with-bg" href="/tags/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6/">前端框架</a>
                    
                      <a class="hover-with-bg" href="/tags/Vue/">Vue</a>
                    
                  </div>
                
              </div>
              
                <p class="note note-warning">
                  
                    本博客所有文章除特别声明外，均采用 <a target="_blank" href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh" rel="nofollow noopener noopener">CC BY-SA 4.0 协议</a> ，转载请注明出处！
                  
                </p>
              
              
                <div class="post-prevnext">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2021/10/04/SpringBoot-SpringBoot%E5%85%A5%E9%97%A8-2021-10-04-1%E3%80%81Spring%E4%B8%8ESpringBoot/">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">1、Spring与SpringBoot</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2021/10/02/%E5%89%8D%E7%AB%AF-Vue-2021-10-02-Vue%E5%9F%BA%E7%A1%80/">
                        <span class="hidden-mobile">Vue基础</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
          </article>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div class="toc-body" id="toc-body"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->


    

    
      <a id="scroll-top-button" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
    

    
  </main>

  <footer class="text-center mt-5 py-3">
  <div class="footer-content">
     <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a> 
  </div>
  

  

  
</footer>


  <!-- SCRIPTS -->
  
  <script  src="https://cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js" ></script>
<script  src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.min.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>

<!-- Plugins -->


  
    <script  src="/js/img-lazyload.js" ></script>
  



  



  <script  src="https://cdn.jsdelivr.net/npm/tocbot@4.12.3/dist/tocbot.min.js" ></script>



  <script  src="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js" ></script>



  <script  src="https://cdn.jsdelivr.net/npm/anchor-js@4.3.1/anchor.min.js" ></script>



  <script defer src="https://cdn.jsdelivr.net/npm/clipboard@2.0.8/dist/clipboard.min.js" ></script>



  <script  src="/js/local-search.js" ></script>






  <script  src="https://cdn.jsdelivr.net/npm/typed.js@2.0.12/lib/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var title = document.getElementById('subtitle').title;
      
      typing(title)
      
    })(window, document);
  </script>














  
<script src="//cdn.jsdelivr.net/gh/bynotes/texiao/source/js/xiaoxuehua.js"></script>
<script src="//cdn.jsdelivr.net/gh/bynotes/texiao/source/js/caidai.js"></script>
<script src="//cdn.jsdelivr.net/gh/bynotes/texiao/source/js/love.js"></script>
<script src="//cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script>
<script src="//cdn.jsdelivr.net/gh/metowolf/MetingJS@1.2/dist/Meting.min.js"></script>



<!-- 主题的启动项 保持在最底部 -->
<script  src="/js/boot.js" ></script>

  <!--动态线条背景-->
  <script type="text/javascript" color="70,119,184" opacity='1' zIndex="-2" count="200" src="//cdn.bootcss.com/canvas-nest.js/1.0.0/canvas-nest.min.js"></script>

<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"model":{"jsonPath":"/live2dw/assets/koharu.model.json"},"display":{"position":"left","width":200,"height":400},"mobile":{"show":false},"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/","tagMode":false});</script></body>
</html>
